具有多个参数的 kvm 超级调用

Gae*_*ano 7 c virtualization kvm virtual-machine

我目前正在尝试使用 kvm 构建一个小型虚拟机管理程序和内核,并且我努力使具有多个 args 的超级调用正常工作。

这是我尝试过的:

// guest.c

#define KVM_HYPERCALL vmcall
// #define KVM_HYPERCALL vmmcall
// #define KVM_HYPERCALL ".byte 0x0f,0x01,0xd9"
// #define KVM_HYPERCALL .byte 0x0f,0x01,0xc1"

static inline long kvm_hypercall4(int nr, unsigned long p1,
                  unsigned long p2, unsigned long p3,
                  unsigned long p4) {
    long ret;
    asm volatile(KVM_HYPERCALL
             : "=a"(ret)
             : "a"(nr), "b"(p1), "c"(p2), "d"(p3), "S"(p4)
             : "memory");
    return ret;
}
Run Code Online (Sandbox Code Playgroud)

这些超级调用中的任何一个都会导致vcpu->kvm_run->exit_reason等于 6,这让我感到惊讶KVM_EXIT_MMIO而不是KVM_EXIT_HYPERCALL

switch (vcpu->kvm_run->exit_reason) {
  case KVM_EXIT_MMIO:
    printf("syscall: %lld\n", vcpu->kvm_run->hypercall.nr); // prints 0
    printf("arg 1: %lld\n",  vcpu->kvm_run->hypercall.args[1]); // prints 0
    printf("arg 2: %lld\n", vcpu->kvm_run->hypercall.args[2]); // prints 0
    printf("arg 3: %lld\n",  vcpu->kvm_run->hypercall.args[3]); // prints 0

    if(ioctl(vcpu->fd, KVM_GET_REGS, &regs)<0) exit 1;

    printf("rax: %lld\n", regs.rax); // prints 0
    printf("rbx: %lld\n", regs.rbx); // prints 0
    printf("rcx: %lld\n", regs.rcx); // prints 0

Run Code Online (Sandbox Code Playgroud)

除了退出原因是KVM_EXIT_MMIO为什么没有设置regs?使用多个参数触发 KVM_EXIT_HYPERCALL 的正确方法是什么?

提前致谢

编辑:以防万一:我正在使用第 9 代 intel i7 cpu,运行带有 linux 内核 5.4 的 debian

mpr*_*net 0

来自内核文档kvm/api

如果 exit_reason 是 KVM_EXIT_MMIO,则 vcpu 执行了 kvm 无法满足的内存映射 I/O 指令。如果“is_write”为真,则“data”成员包含写入的数据,否则应由应用程序代码填充。

您触发的超级调用引发了此类失败。
这取决于您调用的超级调用的代码。