一、模仿一个x86平台虚机

cpu虚拟化原理来源于Linux虚拟化KVM-Qemu分析(四)之CPU虚拟化(2)

笔者就实现了下相关操作。看汇编是在x86平台下操作的,其中两个文件分别是

1.tiny_kernel.S

start:
/* Hello */
mov     $0x48, %al
outb    %al, $0xf1
mov     $0x65, %al
outb    %al, $0xf1
mov     $0x6c, %al
outb    %al, $0xf1
mov     $0x6c, %al
outb    %al, $0xf1
mov     $0x6f, %al
outb    %al, $0xf1
mov     $0x2c, %al
outb    %al, $0xf1

/* world */
mov     $0x77, %al
outb    %al, $0xf1
mov     $0x6f, %al
outb    %al, $0xf1
mov     $0x72, %al
outb    %al, $0xf1
mov     $0x6c, %al
outb    %al, $0xf1
mov     $0x64, %al
outb    %al, $0xf1

mov     $0x0a, %al
outb    %al, $0xf1

hlt

2.tiny_qemu.c        (这个用例程序写得很经典)

#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <assert.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <linux/kvm.h>
#include <sys/mman.h>

#define KVM_DEV     "/dev/kvm"
#define TINY_KERNEL_FILE    "./tiny_kernel.bin"
#define PAGE_SIZE  0x1000

int main(void)
{
    int kvm_fd;
    int vm_fd;
    int vcpu_fd;
    int tiny_kernel_fd;
    int ret;
    int mmap_size;
    
    struct kvm_sregs sregs;
    struct kvm_regs regs;
    struct kvm_userspace_memory_region mem;
    struct kvm_run *kvm_run;
    void *userspace_addr;

    /* open kvm device */
    kvm_fd = open(KVM_DEV, O_RDWR);
    assert(kvm_fd > 0);

    /* create VM */
    vm_fd = ioctl(kvm_fd, KVM_CREATE_VM, 0);
    assert(vm_fd >= 0);

    /* create VCPU */
    vcpu_fd = ioctl(vm_fd, KVM_CREATE_VCPU, 0);
    assert(vcpu_fd >= 0);

    /* open tiny_kernel binary file */
    tiny_kernel_fd = open(TINY_KERNEL_FILE, O_RDONLY);
    assert(tiny_kernel_fd > 0);
    /* map 4K into memory */
    userspace_addr = mmap(NULL, PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0);
    assert(userspace_addr > 0);
    /* read tiny_kernel binary into the memory */
    ret = read(tiny_kernel_fd, userspace_addr, PAGE_SIZE);
    assert(ret >= 0);

    /* set user memory region */
    mem.slot = 0;
    mem.flags = 0;
    mem.guest_phys_addr = 0;
    mem.memory_size = PAGE_SIZE;
    mem.userspace_addr = (unsigned long)userspace_addr;
    ret = ioctl(vm_fd, KVM_SET_USER_MEMORY_REGION, &mem);
    assert(ret >= 0);

    /* get kvm_run */
    mmap_size = ioctl(kvm_fd, KVM_GET_VCPU_MMAP_SIZE, NULL);
    assert(mmap_size >= 0);
    kvm_run = (struct kvm_run *)mmap(NULL, mmap_size, PROT_READ | PROT_WRITE, MAP_SHARED, vcpu_fd, 0);
    assert(kvm_run >= 0);

    /* set cpu registers */
    ret = ioctl(vcpu_fd, KVM_GET_SREGS, &sregs);
    assert(ret >= 0);
    sregs.cs.base = 0;
    sregs.cs.selector = 0;
    ret = ioctl(vcpu_fd, KVM_SET_SREGS, &sregs);
    memset(&regs, 0, sizeof(struct kvm_regs));
    regs.rip = 0;
    ret = ioctl(vcpu_fd, KVM_SET_REGS, &regs);
    assert(ret >= 0);

    /* vcpu run */
    while (1) {
        ret = ioctl(vcpu_fd, KVM_RUN, NULL);
        assert(ret >= 0);

        switch(kvm_run->exit_reason) {
            case KVM_EXIT_HLT:
                printf("----KVM EXIT HLT----\n");
                close(kvm_fd);
                close(tiny_kernel_fd);
                return 0;
            case KVM_EXIT_IO:
                putchar(*(((char *)kvm_run) + kvm_run->io.data_offset));
                break;
            default:
                printf("Unknow exit reason: %d\n", kvm_run->exit_reason);
                break;
        }
    }

    return 0;
}

程序原理很简单,就是模仿kvm-qemu那一套。

二、模仿一个arm平台虚机

本次虚拟机操作来源于https://www.cnblogs.com/pengdonglin137/p/14083316.html

点赞(0) 打赏

评论列表 共有 0 条评论

暂无评论

微信公众账号

微信扫一扫加关注

发表
评论
返回
顶部