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