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 pub fn kvm_arch_dev_ioctl(cmd: u32, _arg: usize) -> Result<usize, SystemError> { 56 match cmd { 57 _ => { 58 kerror!("unknown kvm ioctl cmd: {}", cmd); 59 return Err(SystemError::EINVAL); 60 } 61 } 62 } 63 64 pub fn kvm_arch_vcpu_create(id: u32) -> Result<Arc<Mutex<VmxVcpu>>, SystemError> { 65 // let guest_rip = current_kvm.lock().memslots[0].memslots[0].userspace_addr; 66 let vcpu = VmxVcpu::new(id, vm(0).unwrap()).unwrap(); 67 return Ok(Arc::new(Mutex::new(vcpu))); 68 } 69 70 pub fn kvm_arch_vcpu_setup(vcpu: &Mutex<VmxVcpu>) -> Result<(), SystemError> { 71 kvm_vcpu_mtrr_init(vcpu)?; 72 kvm_mmu_setup(vcpu); 73 Ok(()) 74 } 75 pub fn kvm_arch_vcpu_ioctl_run(_vcpu: &Mutex<VmxVcpu>) -> Result<(), SystemError> { 76 match vmx_vmlaunch() { 77 Ok(_) => {} 78 Err(e) => { 79 let vmx_err = vmx_vmread(VmcsFields::VMEXIT_INSTR_ERR as u32).unwrap(); 80 kdebug!("vmlaunch failed: {:?}", vmx_err); 81 return Err(e); 82 } 83 } 84 Ok(()) 85 } 86 87 // pub fn kvm_arch_create_memslot(_slot: &mut KvmMemorySlot, _npages: u64) { 88 89 // } 90 91 // pub fn kvm_arch_commit_memory_region( 92 // _mem: &KvmUserspaceMemoryRegion, 93 // _new_slot: &KvmMemorySlot, 94 // _old_slot: &KvmMemorySlot, 95 // _change: KvmMemoryChange) { 96 // // let kvm = KVM(); 97 // // let mut num_mmu_pages = 0; 98 // // if kvm.lock().arch.n_requested_mmu_pages == 0{ 99 // // num_mmu_pages = kvm_mmu_calculate_mmu_pages(); 100 // // } 101 // // if num_mmu_pages != 0 { 102 // // // kvm_mmu_change_mmu_pages(num_mmu_pages); 103 // // } 104 // } 105 } 106 107 #[no_mangle] 108 pub extern "C" fn guest_code() { 109 kdebug!("guest_code"); 110 loop { 111 unsafe { 112 asm!("mov rax, 0", "mov rcx, 0", "cpuid"); 113 } 114 unsafe { asm!("nop") }; 115 kdebug!("guest_code"); 116 } 117 } 118