1 use crate::driver::base::device::device_number::DeviceNumber; 2 use crate::filesystem; 3 use crate::filesystem::devfs::DevFS; 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::mm::VirtAddr; 11 use crate::process::ProcessManager; 12 use crate::syscall::user_access::copy_from_user; 13 use crate::virt::kvm::host_mem::KvmUserspaceMemoryRegion; 14 use crate::virt::kvm::update_vm; 15 use crate::virt::kvm::vcpu_dev::LockedVcpuInode; 16 use crate::virt::kvm::vm; 17 use crate::{arch::KVMArch, libs::spinlock::SpinLock, time::PosixTimeSpec}; 18 use alloc::{ 19 string::String, 20 sync::{Arc, Weak}, 21 vec::Vec, 22 }; 23 use log::debug; 24 use system_error::SystemError; 25 26 // pub const KVM_API_VERSION:u32 = 12; 27 // pub const GUEST_STACK_SIZE:usize = 1024; 28 // pub const HOST_STACK_SIZE:usize = 0x1000 * 6; 29 30 /* 31 * ioctls for /dev/vm fds: 32 */ 33 pub const KVM_CREATE_VCPU: u32 = 0x00; 34 pub const KVM_SET_USER_MEMORY_REGION: u32 = 0x01; 35 pub const KVM_GET_DIRTY_LOG: u32 = 0x02; 36 pub const KVM_IRQFD: u32 = 0x03; 37 pub const KVM_IOEVENTFD: u32 = 0x04; 38 pub const KVM_IRQ_LINE_STATUS: u32 = 0x05; 39 40 // #[derive(Debug)] 41 // pub struct InodeInfo { 42 // kvm: Arc<Hypervisor>, 43 // } 44 45 #[derive(Debug)] 46 pub struct VmInode { 47 /// uuid 暂时不知道有什么用(x 48 // uuid: Uuid, 49 /// 指向自身的弱引用 50 self_ref: Weak<LockedVmInode>, 51 /// 指向inode所在的文件系统对象的指针 52 fs: Weak<DevFS>, 53 /// INode 元数据 54 metadata: Metadata, 55 // fdata: InodeInfo, 56 } 57 58 #[derive(Debug)] 59 pub struct LockedVmInode(SpinLock<VmInode>); 60 61 impl LockedVmInode { 62 pub fn new() -> Arc<Self> { 63 let inode = VmInode { 64 self_ref: Weak::default(), 65 fs: Weak::default(), 66 metadata: Metadata { 67 dev_id: 1, 68 inode_id: generate_inode_id(), 69 size: 0, 70 blk_size: 0, 71 blocks: 0, 72 atime: PosixTimeSpec::default(), 73 mtime: PosixTimeSpec::default(), 74 ctime: PosixTimeSpec::default(), 75 file_type: FileType::KvmDevice, // 文件夹,block设备,char设备 76 mode: filesystem::vfs::syscall::ModeType::S_IALLUGO, 77 nlinks: 1, 78 uid: 0, 79 gid: 0, 80 raw_dev: DeviceNumber::default(), // 这里用来作为device number 81 }, 82 // fdata: InodeInfo { 83 // kvm: kvm, 84 // }, 85 }; 86 87 let result = Arc::new(LockedVmInode(SpinLock::new(inode))); 88 result.0.lock().self_ref = Arc::downgrade(&result); 89 90 return result; 91 } 92 } 93 94 impl IndexNode for LockedVmInode { 95 fn as_any_ref(&self) -> &dyn core::any::Any { 96 self 97 } 98 99 fn open( 100 &self, 101 _data: SpinLockGuard<FilePrivateData>, 102 _mode: &FileMode, 103 ) -> Result<(), SystemError> { 104 debug!("file private data:{:?}", _data); 105 return Ok(()); 106 } 107 108 fn close(&self, _data: SpinLockGuard<FilePrivateData>) -> Result<(), SystemError> { 109 return Ok(()); 110 } 111 112 fn metadata(&self) -> Result<Metadata, SystemError> { 113 return Ok(self.0.lock().metadata.clone()); 114 } 115 116 fn fs(&self) -> Arc<dyn FileSystem> { 117 return self.0.lock().fs.upgrade().unwrap(); 118 } 119 120 fn list(&self) -> Result<Vec<String>, SystemError> { 121 Err(SystemError::ENOSYS) 122 } 123 124 fn set_metadata(&self, metadata: &Metadata) -> Result<(), SystemError> { 125 let mut inode = self.0.lock(); 126 inode.metadata.atime = metadata.atime; 127 inode.metadata.mtime = metadata.mtime; 128 inode.metadata.ctime = metadata.ctime; 129 inode.metadata.mode = metadata.mode; 130 inode.metadata.uid = metadata.uid; 131 inode.metadata.gid = metadata.gid; 132 133 return Ok(()); 134 } 135 136 /// @brief io control接口 137 /// 138 /// @param cmd 命令 139 /// @param data 数据 140 /// 141 /// @return 成功:Ok() 142 /// 失败:Err(错误码) 143 fn ioctl( 144 &self, 145 cmd: u32, 146 data: usize, 147 _private_data: &FilePrivateData, 148 ) -> Result<usize, SystemError> { 149 match cmd { 150 0xdeadbeef => { 151 debug!("kvm_vm ioctl"); 152 Ok(0) 153 } 154 KVM_CREATE_VCPU => { 155 debug!("kvm_vcpu ioctl KVM_CREATE_VCPU"); 156 kvm_vm_ioctl_create_vcpu(data as u32) 157 } 158 KVM_SET_USER_MEMORY_REGION => { 159 debug!("kvm_vcpu ioctl KVM_SET_USER_MEMORY_REGION data={:x}", data); 160 let mut kvm_userspace_mem = KvmUserspaceMemoryRegion::default(); // = unsafe { (data as *const KvmUserspaceMemoryRegion).as_ref().unwrap() }; 161 unsafe { 162 copy_from_user( 163 core::slice::from_raw_parts_mut( 164 (&mut kvm_userspace_mem as *mut _) as *mut u8, 165 core::mem::size_of::<KvmUserspaceMemoryRegion>(), 166 ), 167 VirtAddr::new(data), 168 )?; 169 } 170 debug!( 171 "slot={}, flag={}, memory_size={:x}, guest_phys_addr={}, userspace_addr={}", 172 kvm_userspace_mem.slot, 173 kvm_userspace_mem.flags, 174 kvm_userspace_mem.memory_size, 175 kvm_userspace_mem.guest_phys_addr, // starting at physical address guest_phys_addr (from the guest’s perspective) 176 kvm_userspace_mem.userspace_addr // using memory at linear address userspace_addr (from the host’s perspective) 177 ); 178 179 let mut current_vm = vm(0).unwrap(); 180 current_vm.set_user_memory_region(&kvm_userspace_mem)?; 181 update_vm(0, current_vm); 182 Ok(0) 183 } 184 KVM_GET_DIRTY_LOG | KVM_IRQFD | KVM_IOEVENTFD | KVM_IRQ_LINE_STATUS => { 185 Err(SystemError::ENOSYS) 186 } 187 _ => { 188 debug!("kvm_vm ioctl"); 189 Ok(usize::MAX) 190 } 191 } 192 } 193 /// 读设备 - 应该调用设备的函数读写,而不是通过文件系统读写 194 fn read_at( 195 &self, 196 _offset: usize, 197 _len: usize, 198 _buf: &mut [u8], 199 _data: SpinLockGuard<FilePrivateData>, 200 ) -> Result<usize, SystemError> { 201 Err(SystemError::ENOSYS) 202 } 203 204 /// 写设备 - 应该调用设备的函数读写,而不是通过文件系统读写 205 fn write_at( 206 &self, 207 _offset: usize, 208 _len: usize, 209 _buf: &[u8], 210 _data: SpinLockGuard<FilePrivateData>, 211 ) -> Result<usize, SystemError> { 212 Err(SystemError::ENOSYS) 213 } 214 } 215 216 fn kvm_vm_ioctl_create_vcpu(id: u32) -> Result<usize, SystemError> { 217 let vcpu = KVMArch::kvm_arch_vcpu_create(id).unwrap(); 218 KVMArch::kvm_arch_vcpu_setup(vcpu.as_ref())?; 219 220 let mut current_vm = vm(0).unwrap(); 221 current_vm.vcpu.push(vcpu); 222 current_vm.nr_vcpus += 1; 223 update_vm(0, current_vm); 224 225 let vcpu_inode = LockedVcpuInode::new(); 226 let file: File = File::new(vcpu_inode, FileMode::O_RDWR)?; 227 let r = ProcessManager::current_pcb() 228 .fd_table() 229 .write() 230 .alloc_fd(file, None) 231 .map(|fd| fd as usize); 232 return r; 233 } 234