xref: /DragonOS/kernel/src/arch/x86_64/kvm/mod.rs (revision cb02d0bbc213867ac845b7e8a0fb337f723d396a)
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::ENOSYS);
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::ENOSYS);
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