如何以未使用的 x86 操作码在 linux KVM 中实现新指令

Posted

技术标签:

【中文标题】如何以未使用的 x86 操作码在 linux KVM 中实现新指令【英文标题】:How to implement new instruction in linux KVM at unused x86 opcode 【发布时间】:2017-04-24 07:02:10 【问题描述】:

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

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

通过网上的一些资源,我了解了如何定义新的系统调用,但是我不确定linux源代码中的哪些文件需要添加NEWCPUID的代码?有没有比只依赖 'find' 命令更好的方法?

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

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

【问题讨论】:

等等,AFAIK,KVM 实际上并没有做任何仿真。您如何提议添加“新指令”?您是否尝试使用无效的操作码来触发 CPU 异常? 我想他说的是this,毕竟你还是得处理特权指令。不确定这种故障是否也适用于“标准”非法操作码陷阱。 【参考方案1】:

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

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

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

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

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

【讨论】:

以上是关于如何以未使用的 x86 操作码在 linux KVM 中实现新指令的主要内容,如果未能解决你的问题,请参考以下文章

x86 ASM Linux - 使用 .bss 部分

在 Linux for x86 上检测异常浮点操作

Python:如何使 ANSI 转义码在 Windows 中也能正常工作?

Linux 定制X86平台操作系统

如何在汇编 linux x86 中使用 chmod()?

裸机x86组件中的网络连接