目录
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