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是否支持虚拟化
kvm_arch_cpu_supports_vm() -> Result<(), SystemError>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
kvm_arch_init() -> Result<(), SystemError>48 pub fn kvm_arch_init() -> Result<(), SystemError> {
49 Ok(())
50 }
51
52 #[deny(clippy::match_single_binding)]
kvm_arch_dev_ioctl(cmd: u32, _arg: usize) -> Result<usize, SystemError>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
kvm_arch_vcpu_create(id: u32) -> Result<Arc<Mutex<VmxVcpu>>, SystemError>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
kvm_arch_vcpu_setup(vcpu: &Mutex<VmxVcpu>) -> Result<(), SystemError>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 }
kvm_arch_vcpu_ioctl_run(_vcpu: &Mutex<VmxVcpu>) -> Result<(), SystemError>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]
guest_code()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