1 use crate::arch::kvm::vmx::vmcs::VmcsFields; 2 use crate::arch::kvm::vmx::vmx_asm_wrapper::{vmx_vmlaunch, vmx_vmread}; 3 use crate::libs::mutex::Mutex; 4 use crate::virt::kvm::vm; 5 6 use alloc::sync::Arc; 7 use core::arch::asm; 8 use log::{debug, error}; 9 use raw_cpuid::CpuId; 10 use system_error::SystemError; 11 // use crate::virt::kvm::guest_code; 12 use self::vmx::mmu::{kvm_mmu_setup, kvm_vcpu_mtrr_init}; 13 use self::vmx::vcpu::VmxVcpu; 14 pub mod vmx; 15 16 #[derive(Default, Debug, Clone)] 17 pub struct X86_64KVMArch { 18 // n_used_mmu_pages: u32, 19 // n_requested_mmu_pages: u32, 20 // n_max_mmu_pages: u32, 21 // mmu_valid_gen: u64, 22 // // mmu_page_hash:[], 23 // active_mmu_pages: LinkedList<KvmMmuPage>, // 所有分配的mmu page都挂到active_mmu_pages上 24 // zapped_obsolete_pages: LinkedList<KvmMmuPage>, // 释放的mmu page都挂到zapped_obsolete_pages上,一个全局的invalid_list 25 } 26 27 impl X86_64KVMArch { 28 /// @brief 查看CPU是否支持虚拟化 29 pub fn kvm_arch_cpu_supports_vm() -> Result<(), SystemError> { 30 let cpuid = CpuId::new(); 31 // Check to see if CPU is Intel (“GenuineIntel”). 32 if let Some(vi) = cpuid.get_vendor_info() { 33 if vi.as_str() != "GenuineIntel" { 34 return Err(SystemError::ENOSYS); 35 } 36 } 37 // Check processor supports for Virtual Machine Extension (VMX) technology 38 // CPUID.1:ECX.VMX[bit 5] = 1 (Intel Manual: 24.6 Discovering Support for VMX) 39 if let Some(fi) = cpuid.get_feature_info() { 40 if !fi.has_vmx() { 41 return Err(SystemError::ENOSYS); 42 } 43 } 44 Ok(()) 45 } 46 47 /// @brief 初始化KVM 48 pub fn kvm_arch_init() -> Result<(), SystemError> { 49 Ok(()) 50 } 51 52 #[deny(clippy::match_single_binding)] 53 pub fn kvm_arch_dev_ioctl(cmd: u32, _arg: usize) -> Result<usize, SystemError> { 54 error!("unknown kvm ioctl cmd: {}", cmd); 55 return Err(SystemError::EINVAL); 56 } 57 58 pub fn kvm_arch_vcpu_create(id: u32) -> Result<Arc<Mutex<VmxVcpu>>, SystemError> { 59 // let guest_rip = current_kvm.lock().memslots[0].memslots[0].userspace_addr; 60 let vcpu = VmxVcpu::new(id, vm(0).unwrap()).unwrap(); 61 return Ok(Arc::new(Mutex::new(vcpu))); 62 } 63 64 pub fn kvm_arch_vcpu_setup(vcpu: &Mutex<VmxVcpu>) -> Result<(), SystemError> { 65 kvm_vcpu_mtrr_init(vcpu)?; 66 kvm_mmu_setup(vcpu); 67 Ok(()) 68 } 69 pub fn kvm_arch_vcpu_ioctl_run(_vcpu: &Mutex<VmxVcpu>) -> Result<(), SystemError> { 70 match vmx_vmlaunch() { 71 Ok(_) => {} 72 Err(e) => { 73 let vmx_err = vmx_vmread(VmcsFields::VMEXIT_INSTR_ERR as u32).unwrap(); 74 debug!("vmlaunch failed: {:?}", vmx_err); 75 return Err(e); 76 } 77 } 78 Ok(()) 79 } 80 81 // pub fn kvm_arch_create_memslot(_slot: &mut KvmMemorySlot, _npages: u64) { 82 83 // } 84 85 // pub fn kvm_arch_commit_memory_region( 86 // _mem: &KvmUserspaceMemoryRegion, 87 // _new_slot: &KvmMemorySlot, 88 // _old_slot: &KvmMemorySlot, 89 // _change: KvmMemoryChange) { 90 // // let kvm = KVM(); 91 // // let mut num_mmu_pages = 0; 92 // // if kvm.lock().arch.n_requested_mmu_pages == 0{ 93 // // num_mmu_pages = kvm_mmu_calculate_mmu_pages(); 94 // // } 95 // // if num_mmu_pages != 0 { 96 // // // kvm_mmu_change_mmu_pages(num_mmu_pages); 97 // // } 98 // } 99 } 100 101 #[no_mangle] 102 pub extern "C" fn guest_code() { 103 debug!("guest_code"); 104 loop { 105 unsafe { 106 asm!("mov rax, 0", "mov rcx, 0", "cpuid"); 107 } 108 unsafe { asm!("nop") }; 109 debug!("guest_code"); 110 } 111 } 112