1 use crate::driver::base::device::device_number::DeviceNumber; 2 use crate::filesystem; 3 use crate::filesystem::devfs::{DevFS, DeviceINode}; 4 use crate::filesystem::vfs::{ 5 core::generate_inode_id, 6 file::{File, FileMode}, 7 FilePrivateData, FileSystem, FileType, IndexNode, Metadata, 8 }; 9 use crate::libs::spinlock::SpinLockGuard; 10 use crate::process::ProcessManager; 11 use crate::{arch::KVMArch, libs::spinlock::SpinLock, time::PosixTimeSpec}; 12 // use crate::virt::kvm::{host_stack}; 13 use super::push_vm; 14 use crate::virt::kvm::vm_dev::LockedVmInode; 15 use alloc::{ 16 string::String, 17 sync::{Arc, Weak}, 18 vec::Vec, 19 }; 20 use log::debug; 21 use system_error::SystemError; 22 23 pub const KVM_API_VERSION: u32 = 12; 24 25 // use crate::virt::kvm::kvm_dev_ioctl_create_vm; 26 /* 27 * ioctls for /dev/kvm fds: 28 */ 29 pub const KVM_GET_API_VERSION: u32 = 0x00; 30 pub const KVM_CREATE_VM: u32 = 0x01; 31 pub const KVM_CHECK_EXTENSION: u32 = 0x03; 32 pub const KVM_GET_VCPU_MMAP_SIZE: u32 = 0x04; // Get size for mmap(vcpu_fd) in bytes 33 pub const KVM_TRACE_ENABLE: u32 = 0x05; 34 pub const KVM_TRACE_PAUSE: u32 = 0x06; 35 pub const KVM_TRACE_DISABLE: u32 = 0x07; 36 37 #[derive(Debug)] 38 pub struct KvmInode { 39 /// uuid 暂时不知道有什么用(x 40 // uuid: Uuid, 41 /// 指向自身的弱引用 42 self_ref: Weak<LockedKvmInode>, 43 /// 指向inode所在的文件系统对象的指针 44 fs: Weak<DevFS>, 45 /// INode 元数据 46 metadata: Metadata, 47 } 48 49 #[derive(Debug)] 50 pub struct LockedKvmInode(SpinLock<KvmInode>); 51 52 impl LockedKvmInode { 53 pub fn new() -> Arc<Self> { 54 let inode = KvmInode { 55 self_ref: Weak::default(), 56 fs: Weak::default(), 57 metadata: Metadata { 58 dev_id: 1, 59 inode_id: generate_inode_id(), 60 size: 0, 61 blk_size: 0, 62 blocks: 0, 63 atime: PosixTimeSpec::default(), 64 mtime: PosixTimeSpec::default(), 65 ctime: PosixTimeSpec::default(), 66 file_type: FileType::KvmDevice, // 文件夹,block设备,char设备 67 mode: filesystem::vfs::syscall::ModeType::S_IALLUGO, 68 nlinks: 1, 69 uid: 0, 70 gid: 0, 71 raw_dev: DeviceNumber::default(), // 这里用来作为device number 72 }, 73 }; 74 75 let result = Arc::new(LockedKvmInode(SpinLock::new(inode))); 76 result.0.lock().self_ref = Arc::downgrade(&result); 77 78 return result; 79 } 80 } 81 82 impl DeviceINode for LockedKvmInode { 83 fn set_fs(&self, fs: Weak<DevFS>) { 84 self.0.lock().fs = fs; 85 } 86 } 87 88 impl IndexNode for LockedKvmInode { 89 fn as_any_ref(&self) -> &dyn core::any::Any { 90 self 91 } 92 93 fn open( 94 &self, 95 _data: SpinLockGuard<FilePrivateData>, 96 _mode: &FileMode, 97 ) -> Result<(), SystemError> { 98 debug!("file private data:{:?}", _data); 99 return Ok(()); 100 } 101 102 fn close(&self, _data: SpinLockGuard<FilePrivateData>) -> Result<(), SystemError> { 103 return Ok(()); 104 } 105 106 fn metadata(&self) -> Result<Metadata, SystemError> { 107 return Ok(self.0.lock().metadata.clone()); 108 } 109 110 fn fs(&self) -> Arc<dyn FileSystem> { 111 return self.0.lock().fs.upgrade().unwrap(); 112 } 113 114 fn list(&self) -> Result<Vec<String>, SystemError> { 115 Err(SystemError::ENOSYS) 116 } 117 118 fn set_metadata(&self, metadata: &Metadata) -> Result<(), SystemError> { 119 let mut inode = self.0.lock(); 120 inode.metadata.atime = metadata.atime; 121 inode.metadata.mtime = metadata.mtime; 122 inode.metadata.ctime = metadata.ctime; 123 inode.metadata.mode = metadata.mode; 124 inode.metadata.uid = metadata.uid; 125 inode.metadata.gid = metadata.gid; 126 127 return Ok(()); 128 } 129 130 /// @brief io control接口 131 /// 132 /// @param cmd 命令 133 /// @param data 数据 134 /// 135 /// @return 成功:Ok() 136 /// 失败:Err(错误码) 137 fn ioctl( 138 &self, 139 cmd: u32, 140 data: usize, 141 _private_data: &FilePrivateData, 142 ) -> Result<usize, SystemError> { 143 match cmd { 144 0xdeadbeef => { 145 debug!("kvm ioctl"); 146 Ok(0) 147 } 148 KVM_GET_API_VERSION => Ok(KVM_API_VERSION as usize), 149 KVM_CREATE_VM => { 150 debug!("kvm KVM_CREATE_VM"); 151 kvm_dev_ioctl_create_vm(data) 152 } 153 KVM_CHECK_EXTENSION 154 | KVM_GET_VCPU_MMAP_SIZE 155 | KVM_TRACE_ENABLE 156 | KVM_TRACE_PAUSE 157 | KVM_TRACE_DISABLE => Err(SystemError::ENOSYS), 158 _ => KVMArch::kvm_arch_dev_ioctl(cmd, data), 159 } 160 } 161 /// 读设备 - 应该调用设备的函数读写,而不是通过文件系统读写 162 fn read_at( 163 &self, 164 _offset: usize, 165 _len: usize, 166 _buf: &mut [u8], 167 _data: SpinLockGuard<FilePrivateData>, 168 ) -> Result<usize, SystemError> { 169 Err(SystemError::ENOSYS) 170 } 171 172 /// 写设备 - 应该调用设备的函数读写,而不是通过文件系统读写 173 fn write_at( 174 &self, 175 _offset: usize, 176 _len: usize, 177 _buf: &[u8], 178 _data: SpinLockGuard<FilePrivateData>, 179 ) -> Result<usize, SystemError> { 180 Err(SystemError::ENOSYS) 181 } 182 } 183 184 #[no_mangle] 185 pub fn kvm_dev_ioctl_create_vm(_vmtype: usize) -> Result<usize, SystemError> { 186 push_vm(0).expect("need a valid vm!"); 187 188 // 创建vm文件,返回文件描述符 189 let vm_inode = LockedVmInode::new(); 190 let file: File = File::new(vm_inode, FileMode::O_RDWR)?; 191 let r = ProcessManager::current_pcb() 192 .fd_table() 193 .write() 194 .alloc_fd(file, None) 195 .map(|fd| fd as usize); 196 return r; 197 } 198