assembly 如何在linux x86_64上模拟一个iret

7bsow1i6  于 2022-11-13  发布在  Linux
关注(0)|答案(1)|浏览(193)

我正在编写一个基于英特尔VT的调试器。
当NMI-Exiting=1时,vmx-guest中的iret指令的性能会发生变化。因此,我应该自己处理vmx-host中的NMI,否则guest将出现nmi可重入错误。
我查了英特尔手册:
在执行NMI中断处理程序时,处理器禁用对NMI处理程序得其它调用,直到执行下一条IRET指令为止.这种对后续NMI得阻塞可防止对NMI处理程序得调用堆积.
因此,我尝试在vmx主机中模拟一个iret。CPL保持ring 0,并保持堆栈和代码段不变。
下面我写了一个示例代码,它是在vmx-exit之后由NMI引起的:

asm volatile(
    "pushfq \n\t"
    "mov %%cs.%%ax \n\t"
    "push  %%rax\n\t"
    "mov $._restart_code,%%rax \n\t"
    "push %%rax \n\t"
    "iret \n\t"/*manully iret in the host before vmx-entry.*/
    "._restart_code:"
    "nop":);

有谁能给我看看导游吗?

guz6ccqo

guz6ccqo1#

看起来你的代码缺少推送SS和RSP。下面是我的i386和x86_64的代码:https://github.com/lxylxy123456/uberxmhf/blob/6b56acef71528b29e503ec66a2d305ba1b0c65f9/xmhf/src/xmhf-core/xmhf-runtime/xmhf-smpguest/arch/x86/vmx/smpg-x86vmx.c#L500

void xmhf_smpguest_arch_x86vmx_unblock_nmi(void) {
#ifdef __AMD64__
    asm volatile (
        "movq    %%rsp, %%rsi   \r\n"
        "xorq    %%rax, %%rax   \r\n"
        "movw    %%ss, %%ax     \r\n"
        "pushq   %%rax          \r\n"
        "pushq   %%rsi          \r\n"
        "pushfq                 \r\n"
        "xorq    %%rax, %%rax   \r\n"
        "movw    %%cs, %%ax     \r\n"
        "pushq   %%rax          \r\n"
        "pushq   $1f            \r\n"
        "iretq                  \r\n"
        "1: nop                 \r\n"
        : // no output
        : // no input
        : "%rax", "%rsi", "cc", "memory");
#elif defined(__I386__)
    asm volatile (
        "pushfl                 \r\n"
        "xorl    %%eax, %%eax   \r\n"
        "movw    %%cs, %%ax     \r\n"
        "pushl   %%eax          \r\n"
        "pushl   $1f            \r\n"
        "iretl                  \r\n"
        "1: nop                 \r\n"
        : // no output
        : // no input
        : "%eax", "cc", "memory");
#else /* !defined(__I386__) && !defined(__AMD64__) */
    #error "Unsupported Arch"
#endif /* !defined(__I386__) && !defined(__AMD64__) */
}

相关问题