現在、kvmを使用して小さなハイパーバイザーとカーネルを構築しようとしていますが、複数の引数を持つハイパーコールが正しく機能するように努力しています。
これが私が試したものです:
// 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;
}
これらのハイパーコールのいずれかが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, ®s)<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
終了理由は別にしてKVM_EXIT_MMIO
なぜ登録が設定されていないのですか?複数の引数でKVM_EXIT_HYPERCALLをトリガーする正しい方法は何ですか?
前もって感謝します
編集:それが重要な場合:私はLinuxカーネル5.4でdebianを実行している第9世代インテルi7 CPUを使用しています
documentation によると、KVM_EXIT_HYPERCALL
は使用されなくなりました。
/* KVM_EXIT_HYPERCALL */ struct { __u64 nr; __u64 args[6]; __u64 ret; __u32 longmode; __u32 pad; } hypercall;
未使用。これはかつて「ユーザー空間へのハイパーコール」に使用されていました。このような機能を実装するには、KVM_EXIT_IO(x86)またはKVM_EXIT_MMIO(s390を除くすべて)を使用します。注KVM_EXIT_IOは、KVM_EXIT_MMIOよりも大幅に高速です。
また、KVM_EXIT_HYPERCALL
も実装されていないようです。 grepによる迅速でダーティーな検索。定義されていますが、exit_reason
として割り当てられることはありません。
user@Host:~/Linux/src> grep -R KVM_EXIT_HYPERCALL
include/uapi/linux/kvm.h:#define KVM_EXIT_HYPERCALL 3
include/uapi/linux/kvm.h: /* KVM_EXIT_HYPERCALL */
Documentation/virt/kvm/api.rst: /* KVM_EXIT_HYPERCALL */
tools/include/uapi/linux/kvm.h:#define KVM_EXIT_HYPERCALL 3
tools/include/uapi/linux/kvm.h: /* KVM_EXIT_HYPERCALL */
tools/testing/selftests/kvm/lib/kvm_util.c: {KVM_EXIT_HYPERCALL, "HYPERCALL"},
user@Host:~/Linux/src>
Linuxバージョン:
user@Host:~/Linux/src> git-describe --tags
v5.6-10895-g4c205c84e249
user@Host:~/Linux/src>
このサイトには、古い 質問 カスタムVMCALLを実装する方法が2つあります。それらを試しましたか?
カーネルのドキュメントから kvm/api
Exit_reasonがKVM_EXIT_MMIOの場合、vcpuはkvmで満たすことができなかったメモリマップI/O命令を実行しました。 'is'write'がtrueの場合、 'data'メンバーには書き込まれたデータが含まれ、それ以外の場合はアプリケーションコードで埋める必要があります。
トリガーしたハイパーコールがこのような失敗を引き起こしました。
これは、呼び出したハイパーコールのコードによって異なります。