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