Rust 实现 kvmsample

目录

打开 KVM

创建虚拟机

分配内存

加载 Guest 虚拟机代码

分配 CPU

启动虚拟机

处理 VM_EXIT

编译运行


GitHub - BillXiang/kvmsample: minivm based on kvm

本项目主要用 Rust 重写了 kvmsample, 用于学习 Rust 以及基本 KVM 操作.

  • 打开 KVM

fn kvm_init() -> Kvm {
    const KVM_DEVICE:&str = "/dev/kvm";
    let kvm_path = CString::new(KVM_DEVICE).unwrap();
    Kvm::new_with_path(&kvm_path).unwrap()
}
  • 创建虚拟机

let vm_fd = Kvm::create_vm(kvm).unwrap();
  • 分配内存

let ram_size = ram_size as u64;
let ram_start = unsafe {
    libc::mmap(
        null_mut(),
        ram_size as usize,
        libc::PROT_READ | libc::PROT_WRITE,
        libc::MAP_ANONYMOUS | libc::MAP_SHARED | libc::MAP_NORESERVE,
        -1,
        0
    ) as *mut u8
};
let mem = kvm_userspace_memory_region {
    slot: 0,
    flags: KVM_MEM_LOG_DIRTY_PAGES,
    guest_phys_addr: 0,
    memory_size: ram_size,
    userspace_addr: ram_start as u64
};
unsafe {
    vm_fd.set_user_memory_region(mem).unwrap();
}
  • 加载 Guest 虚拟机代码

fn load_binary(ram_start: *mut u8, test: i32) {
    let binary_file:&str;
    if test == 0 {
        binary_file = "test.bin"
    } else {
        binary_file = "test2.bin"
    }
    match File::open(binary_file) {
        Ok(mut file) => {
            // let len = file.metadata().unwrap().len();
            let mut buffer: Vec<u8> = Vec::new();
            let len = file.read_to_end(&mut buffer).unwrap();
            unsafe {
                let mut slice = slice::from_raw_parts_mut(ram_start, len as usize);
                slice.write(&buffer[..]).unwrap();
            }
        },
        Err(_) => eprintln!("can not open binary file")
    }
}
  • 分配 CPU

fn kvm_init_vcpu(vm_fd: VmFd, vcpu_id: u64) -> VcpuFd {
    vm_fd.create_vcpu(vcpu_id).unwrap()
}
  • 启动虚拟机

fn kvm_run_vm(mut vcpu_fd: VcpuFd) -> JoinHandle<()> {
    let handle = std::thread::spawn(move|| {
        MyKvm::kvm_cpu_thread(&mut vcpu_fd);
    });
    handle
}
  • 处理 VM_EXIT

fn kvm_cpu_thread(vcpu_fd: &mut VcpuFd) {
    MyKvm::kvm_reset_vcpu(vcpu_fd);
    loop {
        match vcpu_fd.run().expect("run failed") {
            VcpuExit::IoIn(addr, _data ) => {
                println!("KVM_EXIT_IO_IN addr {}", addr);
            }
            VcpuExit::IoOut(addr, data) => {
                println!("KVM_EXIT_IO_OUT addr:{} data:{}", addr, data[0]);
            }
            VcpuExit::Unknown => {
                println!("KVM_EXIT_UNKNOWN");
            }
            VcpuExit::Debug(_debug) => {
                println!("KVM_EXIT_DEBUG");
            }
            VcpuExit::MmioRead(_addr, _data ) => {
                println!("KVM_EXIT_MMIO_READ");
            }
            VcpuExit::MmioWrite(_addr, _data ) => {
                println!("KVM_EXIT_MMIO_WRITE");
            }
            VcpuExit::Intr => {
                println!("KVM_EXIT_INTR");
            }
            VcpuExit::Shutdown => {
                println!("KVM_EXIT_SHUTDOWN");
                break;
            }
            r => panic!("KVM PANIC {:?}", r)
        }
    }
}
  • 编译运行

cd kvmsample
make
cp test*.bin kvmsample-rust
cd kvmsample-rust
cargo run

两个vm中分别执行IO_OUT和IO_IN:

KVM_EXIT_IO_OUT addr:16 data:84
KVM_EXIT_IO_IN addr 16
KVM_EXIT_IO_OUT addr:16 data:85
KVM_EXIT_IO_IN addr 16
KVM_EXIT_IO_OUT addr:16 data:86
KVM_EXIT_IO_IN addr 16
KVM_EXIT_IO_OUT addr:16 data:87
KVM_EXIT_IO_IN addr 16
KVM_EXIT_IO_OUT addr:16 data:88
KVM_EXIT_IO_IN addr 16
KVM_EXIT_IO_OUT addr:16 data:89
KVM_EXIT_IO_IN addr 16
KVM_EXIT_IO_OUT addr:16 data:90
KVM_EXIT_IO_IN addr 16
KVM_EXIT_IO_OUT addr:16 data:91
KVM_EXIT_IO_IN addr 16
KVM_EXIT_IO_OUT addr:16 data:92
KVM_EXIT_IO_IN addr 16
KVM_EXIT_IO_OUT addr:16 data:93
KVM_EXIT_IO_IN addr 16
KVM_EXIT_IO_OUT addr:16 data:94
KVM_EXIT_IO_IN addr 16
KVM_EXIT_IO_OUT addr:16 data:95
KVM_EXIT_IO_IN addr 16
KVM_EXIT_IO_OUT addr:16 data:96
KVM_EXIT_IO_IN addr 16
KVM_EXIT_IO_OUT addr:16 data:97
KVM_EXIT_IO_IN addr 16
KVM_EXIT_IO_OUT addr:16 data:98
KVM_EXIT_IO_IN addr 16
KVM_EXIT_IO_OUT addr:16 data:99
KVM_EXIT_IO_IN addr 16
KVM_EXIT_IO_OUT addr:16 data:100
KVM_EXIT_IO_IN addr 16
KVM_EXIT_IO_OUT addr:16 data:101
KVM_EXIT_IO_IN addr 16
KVM_EXIT_IO_OUT addr:16 data:102
KVM_EXIT_IO_IN addr 16
KVM_EXIT_IO_OUT addr:16 data:103
KVM_EXIT_IO_IN addr 16
KVM_EXIT_IO_OUT addr:16 data:104
KVM_EXIT_IO_IN addr 16
KVM_EXIT_IO_OUT addr:16 data:105
KVM_EXIT_IO_IN addr 16
KVM_EXIT_IO_OUT addr:16 data:106
KVM_EXIT_IO_IN addr 16
KVM_EXIT_IO_OUT addr:16 data:107
KVM_EXIT_IO_IN addr 16
KVM_EXIT_IO_OUT addr:16 data:108
KVM_EXIT_IO_IN addr 16
KVM_EXIT_IO_OUT addr:16 data:109^C

  • 14
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值