mod.rs 3.6 KB

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