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