2

作为理解虚拟化的一部分,我正在尝试扩展对 KVM 的支持并定义一个新指令。该指令将使用以前未使用的操作码。参考 ref.x86asm.net/coder32.html。

现在,让我们说一个像“CPUID”这样的指令(它会导致 vm-exit),我想添加一个新指令,比如 -“NEWCPUID”,它类似于特权中的“CPUID”并且被管理程序捕获,但会实现方式不同。

浏览了一些网上资源后,我能够理解如何定义新的系统调用,但我不确定我需要在 linux 源代码中的哪些文件中添加 NEWCPUID 的代码?有没有比仅依赖“查找”命令更好的方法?

我面临以下挑战: 1.我需要在linux源代码中的哪些地方添加代码?2. 不确定这条新指令如何映射到以前未使用的操作码?

由于我对这个领域完全陌生并且愿意学习这个,有人可以简单地解释我如何完成这项任务吗?我需要正确的方向来实现这一目标。如果有描述该过程的参考/教程/博客,那将有很大帮助!

4

1 回答 1

1

以下是您的一些问题的答案:

  1. ...但我不确定我需要为 NEWCPUID 添加代码中的哪些 linux 源代码中的所有文件?A - 为 KVM 添加仿真的正确位置是 arch/x86/kvm/emulate.c。看看 opcode_table[] 是如何定义的以及它们执行的函数的挂钩。基本思想是客户执行未定义的指令,例如“db 0xunused”;由于指令未定义,这将导致退出。在 KVM 中,您查看来自 VMCS/VMCB 的 rip 并确定它是否是 KVM 知道的指令(例如 NEWCPUID),然后 KVM 调用 x86_emulate_instruction()。

  2. ...有没有比仅依靠“查找”命令更好的方法?A - 是的,选择一个示例系统调用,然后使用符号交叉引用,例如 cscope。

  3. ...简而言之,我该如何完成这项任务?A - 正如我在 1 中提到的,首先找到一种方法让来宾尝试执行这个未使用的操作码(例如 db 技巧)。我认为汇编器会尝试拒绝未知的操作码。所以,这是第一步。其次,检查您的指令是否导致 vmexit()。为此,您可以使用跟踪。跟踪会发出大量输出,因此,您必须使用一些过滤器选项。如果跟踪过多,只需在 vmx_handle_exit (vmx.c) 中打印一些内容。最后,找到一种从这里挂钩到您的自定义函数的方法。KVM 已经有handle_exception() 来处理guest 异常;那将是插入自定义函数的好地方。查看此函数如何调用 emulate_instruction 来模拟要注入来宾的异常。

我故意跳过了一些问题,因为我认为它们对于在学习过程中弄清楚自己是必不可少的。顺便说一句,我认为这可能不是理解虚拟化的最佳方式。更好的方法可能是编写自己的用户空间管理程序,通过 /dev/kvm 使用 kvm 服务,或者只是一个独立的管理程序。

于 2017-04-28T19:12:11.673 回答