如何在 Linux x86_64 上模拟 iret

2024-05-10

我正在编写一个基于 Intel VT 的调试器。

由于当 NMI-Exiting=1 时,iret 指令在 vmx-guest 中的性能发生了变化。 所以我应该自己处理vmx主机中的NMI,否则,guest会出现nmi可重入错误。

我查了英特尔手册:

当 NMI 中断处理程序正在执行时,处理器会禁用 对 NMI 处理程序的额外调用,直到下一个 IRET 指令 被执行。这种对后续 NMI 的阻止可以防止堆叠 调用 NMI 处理程序。

所以我尝试自己在 vmx-host 中模拟 iret。 CPL 保留ring0 并保持堆栈和代码段不变。

我在下面编写了一个示例代码,它是在 NMI 导致 vmx-exit 之后:

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":);

任何人都可以展示一些指南吗?


看起来您的代码缺少推动 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 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__) */
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何在 Linux x86_64 上模拟 iret 的相关文章

  • sendfile64 只复制约2GB

    我需要使用 sendfile64 复制大约 16GB 的文件 到目前为止我所取得的成就是 include
  • fopen 不返回

    我在 C 程序中使用 fopen 以只读模式 r 打开文件 但就我而言 我观察到 fopen 调用没有返回 它不返回 NULL 或有效指针 执行在 fopen 调用时被阻止 文件补丁绝对正确 我已经验证过 并且不存在与权限相关的问题 任何人
  • Linux 中的动态环境变量?

    Linux 中是否可以通过某种方式拥有动态环境变量 我有一个网络服务器 网站遵循以下布局 site qa production 我想要一个环境变量 例如 APPLICATION ENV 当我在 qa 目录中时设置为 qa 当我在生产目录中时
  • 为什么在展开的 ADD 循环内重新初始化寄存器会使其运行速度更快,即使循环内有更多指令?

    我有以下代码 include
  • 避免 gcc 函数序言开销?

    我最近遇到了很多 gcc 在 x86 上生成非常糟糕的代码的函数 它们都符合以下模式 if some condition do something really simple and return else something comple
  • Linux 内核标识符中前导和尾随下划线的含义是什么?

    我不断遇到一些小约定 比如 KERNEL Are the 在这种情况下 是内核开发人员使用的命名约定 还是以这种方式命名宏的语法特定原因 整个代码中有很多这样的例子 例如 某些函数和变量以 甚至 这有什么具体原因吗 它似乎被广泛使用 我只需
  • Linux内核container_of宏和C90中的通用容器

    是否有可能实施容器的 http lxr linux no linux tools perf util include linux kernel h L18纯C90中的宏 我不确定如何做到这一点 因为内核实现取决于海湾合作委员会黑客 http
  • os.Mkdir 和 os.MkdirAll 权限

    我正在尝试在程序开始时创建一个日志文件 我需要检查是否 log如果不创建目录 则目录存在 然后继续创建日志文件 好吧 我尝试使用os Mkdir 也os MkdirAll 但无论我在第二个参数中输入什么值 我都会得到一个没有权限的锁定文件夹
  • Linux:在文件保存时触发 Shell 命令

    我想在修改文件时自动触发 shell 命令 我认为这可以通过注册 inotify 挂钩并调用来在代码中完成system 但是是否有更高级别的 bash 命令可以完成此任务 尝试 inotify 工具 我在复制链接时遇到问题 抱歉 但 Git
  • 使用sk_buff添加以太网帧头

    我有一个捕获传出互联网流量的内核模块 Netfilter hook LOCAL OUT 在此挂钩处 仍然没有以太网标头 我构建了以太网头并且可以使用了 但是如何将其连接到skb这样我就可以将整个 skb 结构发送到dev queue xmi
  • Linux:如何从特定端口发送TCP数据包?

    如何打开原始套接字以从特定 TCP 端口发送 我希望所有连接始终来自临时端口以下的一系列端口 如果您正在使用raw套接字 然后只需在数据包标头中填写正确的 TCP 源端口即可 相反 如果您使用 TCP 套接字接口 socket connec
  • 英特尔的最后分支记录功能是英特尔处理器独有的吗?

    最后分支记录是指存储与最近执行的分支相关的源地址和目标地址的寄存器对 MSR 的集合 它们受英特尔酷睿 2 英特尔至强和英特尔凌动处理器系列的支持 http css csail mit edu 6 858 2012 readings ia3
  • 使用 sh 运行 bash 脚本

    我有 bash 脚本 它需要 bash 另一个人尝试运行它 sh script name sh 它失败了 因为 sh 是他的发行版中 dash 的符号链接 ls la bin sh lrwxrwxrwx 1 root root 4 Aug
  • 汇编器8086将32位数字除以16位数字

    我尝试将 32 位数字除以 16 位数字 例如 10000000h 除以 2000h 根据我尝试做的设计除以 右 4 位数字除以除数 然后左 4 位数字除以除数 这是我的代码 DATA num dd 10000000h divisor dw
  • jpegtran 优化而不更改文件名

    我需要优化一些图像 但不更改它们的名称 jpegtran copy none optimize image jpg gt image jpg 但是 这似乎创建了 0 的文件大小 当我对不同的文件名执行此操作时 大小仍然完全相同 怎么样 jp
  • C语言中如何通过内存地址映射函数名和行号?

    如何用 GCC 中的内存地址映射回函数名称和行号 即假设一个 C 语言原型 void func Get the address of caller maybe this could be avoided MemoryAddress get
  • 将 jar 作为 Linux 服务运行 - init.d 脚本在启动应用程序时卡住

    我目前正在致力于在 Linux VM 上实现一个可运行的 jar 作为后台服务 我已经使用了找到的例子here https gist github com shirish4you 5089019作为工作的基础 并将 start 方法修改为
  • 在我的 index.php 中加载 CSS 和 JS 等资源时出现错误 403

    我使用的是 Linux Elementary OS 并在 opt 中安装了 lampp My CSS and JS won t load When I inspect my page through browser The console
  • 查找哪些页面不再与写入时复制共享

    假设我在 Linux 中有一个进程 我从中fork 另一个相同的过程 后forking 因为原始进程将开始写入内存 Linux写时复制机制将为进程提供与分叉进程使用的不同的唯一物理内存页 在执行的某个时刻 我如何知道原始进程的哪些页面已被写
  • 如何确保应用程序在 Linux 上持续运行

    我试图确保脚本在开发服务器上保持运行 它会整理统计数据并提供网络服务 因此它应该会持续存在 但一天中有几次 它会因未知原因而消失 当我们注意到时 我们只需再次启动它 但这很麻烦 并且某些用户没有权限 或专有技术 来启动它 作为一名程序员 我

随机推荐