xref: /DragonOS/kernel/src/virt/kvm/kvm_dev.rs (revision 3959e94df38073fdb80b199777015f95611ba05f)
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::EOPNOTSUPP_OR_ENOTSUP)
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::EOPNOTSUPP_OR_ENOTSUP),
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::EOPNOTSUPP_OR_ENOTSUP)
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::EOPNOTSUPP_OR_ENOTSUP)
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