xref: /DragonOS/kernel/src/virt/kvm/kvm_dev.rs (revision 2b7818e80e00fcfe4d03533f587cc125ea5e4bec)
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