kvm hypercall với nhiều đối số


8

Tôi hiện đang cố gắng xây dựng một trình ảo hóa nhỏ và kernel bằng kvm và tôi đấu tranh để có được các siêu văn bản với nhiều đối số hoạt động chính xác.

Đây là những gì tôi đã thử:

// 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;
}

Bất kỳ Hypercalls nào cũng dẫn đến vcpu->kvm_run->exit_reasonbằng 6, điều này làm tôi ngạc nhiên KVM_EXIT_MMIOthay vì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

Ngoài lý do thoát là KVM_EXIT_MMIOtại sao các reg không được đặt? Cách đúng để kích hoạt KVM_EXIT_HYPERCALL với nhiều đối số là gì?

Cảm ơn trước

EDIT: Trong trường hợp có vấn đề: Tôi đang sử dụng intel i7 cpu thế hệ thứ 9 đang chạy debian với kernel linux 5.4

Câu trả lời:


1

KVM_EXIT_HYPERCALLkhông còn được sử dụng, theo tài liệu :

/* KVM_EXIT_HYPERCALL */
      struct {
          __u64 nr;
          __u64 args[6];
          __u64 ret;
          __u32 longmode;
          __u32 pad;
      } hypercall;

Không sử dụng. Điều này đã từng được sử dụng cho 'hypercall to userpace'. Để thực hiện chức năng đó, hãy sử dụng KVM_EXIT_IO (x86) hoặc KVM_EXIT_MMIO (tất cả ngoại trừ s390). Lưu ý KVM_EXIT_IO nhanh hơn đáng kể so với KVM_EXIT_MMIO.

Và dường như với tôi điều đó KVM_EXIT_HYPERCALLcũng không được thực hiện. Tìm kiếm nhanh và bẩn với grep . Nó được định nghĩa, nhưng sẽ không bao giờ được chỉ định là 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>

Phiên bản Linux:

user@host:~/Linux/src> git-describe --tags
v5.6-10895-g4c205c84e249
user@host:~/Linux/src>

Có một câu hỏi cũ hơn về cách triển khai VMCALL tùy chỉnh với hai câu trả lời trên trang web này. Bạn đã thử chúng chưa?


Các câu trả lời chỉ trình bày cách tạo siêu văn bản với 0 đối số bằng cách sử dụng kvm_hypercall0 hoặc lắp ráp. Tuy nhiên, tôi đang cố gắng để nó hoạt động cho nhiều đối số và kvm_hypercallN được cung cấp trong hệ thống của tôi dường như không hoạt động như mong đợi. Chẳng hạn, tôi mong đợi regs.rax sẽ có các giá trị tôi đã gán trong chương trình khách của mình
Gaetano

0

Từ tài liệu kernel kvm / api

Nếu exit_reason là KVM_EXIT_MMIO, thì vcpu đã thực thi một lệnh I / O được ánh xạ bộ nhớ mà kvm không thể thỏa mãn. Thành viên 'dữ liệu' chứa dữ liệu bằng văn bản nếu 'is_write' là đúng và phải được điền bởi mã ứng dụng.

Hypercall bạn trigled đưa ra thất bại như vậy.
Điều này phụ thuộc vào mã của hypercall mà bạn đã gọi.


1) Tôi đã thực hiện một vmcall chứ không phải IO 2) Làm cách nào để thiết lập các thanh ghi và VMM chính xác để tôi có thể chuyển nhiều đối số thông qua các thanh ghi cho VMM? - Tôi hy vọng rằng tôi sẽ có thể đọc các thanh ghi thông qua ioctl (KVM_GET_REGS, & regs) nhưng tất cả các reg dường như bằng không
Gaetano

@Gaetano Tôi đoán vmcall được nâng KVM_EXIT_MMIO như một ngoại lệ, vẫn không undersood lý do tại sao bạn đang redefinng KVM_HYPERCALL thay vì sử dụng các định nghĩa trong kvm_para.h hoặc một trong kiến trúc tương ứng của bạn
mpromonet

Cảm ơn vì đã trả lời. Tôi đang sử dụng kvm_para.h nhưng vì mục đích khắc phục sự cố, tôi đã sao chép và dán nó vào dự án của mình và ở đây để có khả năng cho phép những người khác có nền tảng không phải là kvm tham gia thảo luận. Cuối cùng, về việc sử dụng VT-X / AMD-V một cách chính xác
Gaetano
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.