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