kvm_dev.rs 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494
  1. use core::intrinsics::unlikely;
  2. use alloc::sync::{Arc, Weak};
  3. use log::{debug, warn};
  4. use system_error::SystemError;
  5. use crate::{
  6. arch::{
  7. vm::{kvm_host::KvmCommonRegs, uapi::UapiKvmSegmentRegs},
  8. MMArch,
  9. },
  10. driver::base::device::device_number::DeviceNumber,
  11. filesystem::{
  12. devfs::{devfs_register, DevFS, DeviceINode},
  13. vfs::{
  14. file::{File, FileMode},
  15. syscall::ModeType,
  16. vcore::generate_inode_id,
  17. FileType, IndexNode, Metadata,
  18. },
  19. },
  20. libs::spinlock::SpinLock,
  21. mm::MemoryManagementArch,
  22. process::ProcessManager,
  23. syscall::user_access::{UserBufferReader, UserBufferWriter},
  24. time::PosixTimeSpec,
  25. virt::vm::user_api::{KvmUserspaceMemoryRegion, PosixKvmUserspaceMemoryRegion},
  26. };
  27. use super::kvm_host::{vcpu::LockedVirtCpu, LockedVm};
  28. #[derive(Debug)]
  29. pub struct KvmInode {
  30. /// 指向自身的弱引用
  31. self_ref: Weak<LockedKvmInode>,
  32. /// 指向inode所在的文件系统对象的指针
  33. fs: Weak<DevFS>,
  34. /// INode 元数据
  35. metadata: Metadata,
  36. }
  37. #[derive(Debug)]
  38. pub struct LockedKvmInode {
  39. inner: SpinLock<KvmInode>,
  40. }
  41. impl LockedKvmInode {
  42. const KVM_CREATE_VM: u32 = 0xAE01;
  43. const KVM_GET_VCPU_MMAP_SIZE: u32 = 0xAE04;
  44. pub fn new() -> Arc<Self> {
  45. let inode = KvmInode {
  46. self_ref: Weak::default(),
  47. fs: Weak::default(),
  48. metadata: Metadata {
  49. dev_id: 1,
  50. inode_id: generate_inode_id(),
  51. size: 0,
  52. blk_size: 0,
  53. blocks: 0,
  54. atime: PosixTimeSpec::default(),
  55. mtime: PosixTimeSpec::default(),
  56. ctime: PosixTimeSpec::default(),
  57. btime: PosixTimeSpec::default(),
  58. file_type: FileType::KvmDevice, // 文件夹,block设备,char设备
  59. mode: ModeType::S_IALLUGO,
  60. nlinks: 1,
  61. uid: 0,
  62. gid: 0,
  63. raw_dev: DeviceNumber::default(), // 这里用来作为device number
  64. },
  65. };
  66. let result = Arc::new(LockedKvmInode {
  67. inner: SpinLock::new(inode),
  68. });
  69. result.inner.lock().self_ref = Arc::downgrade(&result);
  70. return result;
  71. }
  72. fn create_vm(&self, vm_type: usize) -> Result<usize, SystemError> {
  73. let kvm = LockedVm::create(vm_type)?;
  74. let instance = KvmInstance::new(kvm);
  75. let current = ProcessManager::current_pcb();
  76. let file = File::new(instance, FileMode::O_RDWR)?;
  77. let fd = current.fd_table().write().alloc_fd(file, None)?;
  78. return Ok(fd as usize);
  79. }
  80. }
  81. impl DeviceINode for LockedKvmInode {
  82. fn set_fs(&self, fs: Weak<DevFS>) {
  83. self.inner.lock().fs = fs;
  84. }
  85. }
  86. impl IndexNode for LockedKvmInode {
  87. fn open(
  88. &self,
  89. _data: crate::libs::spinlock::SpinLockGuard<crate::filesystem::vfs::FilePrivateData>,
  90. _mode: &FileMode,
  91. ) -> Result<(), SystemError> {
  92. Ok(())
  93. }
  94. fn read_at(
  95. &self,
  96. _offset: usize,
  97. _len: usize,
  98. _buf: &mut [u8],
  99. _data: crate::libs::spinlock::SpinLockGuard<crate::filesystem::vfs::FilePrivateData>,
  100. ) -> Result<usize, system_error::SystemError> {
  101. Err(SystemError::ENOSYS)
  102. }
  103. fn write_at(
  104. &self,
  105. _offset: usize,
  106. _len: usize,
  107. _buf: &[u8],
  108. _data: crate::libs::spinlock::SpinLockGuard<crate::filesystem::vfs::FilePrivateData>,
  109. ) -> Result<usize, system_error::SystemError> {
  110. Err(SystemError::ENOSYS)
  111. }
  112. fn fs(&self) -> Arc<dyn crate::filesystem::vfs::FileSystem> {
  113. self.inner.lock().fs.upgrade().unwrap()
  114. }
  115. fn as_any_ref(&self) -> &dyn core::any::Any {
  116. self
  117. }
  118. fn list(&self) -> Result<alloc::vec::Vec<alloc::string::String>, system_error::SystemError> {
  119. Err(SystemError::ENOSYS)
  120. }
  121. fn metadata(&self) -> Result<Metadata, system_error::SystemError> {
  122. Ok(self.inner.lock().metadata.clone())
  123. }
  124. fn ioctl(
  125. &self,
  126. cmd: u32,
  127. arg: usize,
  128. _private_data: &crate::filesystem::vfs::FilePrivateData,
  129. ) -> Result<usize, SystemError> {
  130. match cmd {
  131. Self::KVM_CREATE_VM => {
  132. let ret = self.create_vm(arg);
  133. warn!("[KVM]: KVM_CREATE_VM {ret:?}");
  134. return ret;
  135. }
  136. Self::KVM_GET_VCPU_MMAP_SIZE => {
  137. if arg != 0 {
  138. return Err(SystemError::EINVAL);
  139. }
  140. debug!("[KVM] KVM_GET_VCPU_MMAP_SIZE");
  141. return Ok(MMArch::PAGE_SIZE);
  142. }
  143. _ => {
  144. // TODO: arch_ioctl
  145. warn!("[KVM]: unknown iooctl cmd {cmd:x}");
  146. }
  147. }
  148. Ok(0)
  149. }
  150. fn close(
  151. &self,
  152. _data: crate::libs::spinlock::SpinLockGuard<crate::filesystem::vfs::FilePrivateData>,
  153. ) -> Result<(), SystemError> {
  154. Ok(())
  155. }
  156. }
  157. #[derive(Debug)]
  158. pub struct KvmInstance {
  159. kvm: Arc<LockedVm>,
  160. metadata: Metadata,
  161. }
  162. impl KvmInstance {
  163. const KVM_CREATE_VCPU: u32 = 0xAE41;
  164. const KVM_SET_USER_MEMORY_REGION: u32 = 0x4020AE46;
  165. pub fn new(vm: Arc<LockedVm>) -> Arc<Self> {
  166. Arc::new(Self {
  167. kvm: vm,
  168. metadata: Metadata {
  169. dev_id: 1,
  170. inode_id: generate_inode_id(),
  171. size: 0,
  172. blk_size: 0,
  173. blocks: 0,
  174. atime: PosixTimeSpec::default(),
  175. mtime: PosixTimeSpec::default(),
  176. ctime: PosixTimeSpec::default(),
  177. btime: PosixTimeSpec::default(),
  178. file_type: FileType::KvmDevice,
  179. mode: ModeType::S_IALLUGO,
  180. nlinks: 1,
  181. uid: 0,
  182. gid: 0,
  183. raw_dev: DeviceNumber::default(), // 这里用来作为device number
  184. },
  185. })
  186. }
  187. }
  188. impl IndexNode for KvmInstance {
  189. fn open(
  190. &self,
  191. _data: crate::libs::spinlock::SpinLockGuard<crate::filesystem::vfs::FilePrivateData>,
  192. _mode: &crate::filesystem::vfs::file::FileMode,
  193. ) -> Result<(), SystemError> {
  194. Ok(())
  195. }
  196. #[inline(never)]
  197. fn ioctl(
  198. &self,
  199. cmd: u32,
  200. arg: usize,
  201. _private_data: &crate::filesystem::vfs::FilePrivateData,
  202. ) -> Result<usize, SystemError> {
  203. debug!("kvm instance ioctl cmd {cmd:x}");
  204. match cmd {
  205. Self::KVM_CREATE_VCPU => {
  206. let ret = self.kvm.lock().create_vcpu(arg);
  207. debug!("[KVM] create vcpu fd {ret:?}");
  208. return ret;
  209. }
  210. Self::KVM_SET_USER_MEMORY_REGION => {
  211. debug!("[KVM-INSTANCE] KVM_SET_USER_MEMORY_REGION");
  212. let user_reader = UserBufferReader::new(
  213. arg as *const PosixKvmUserspaceMemoryRegion,
  214. core::mem::size_of::<PosixKvmUserspaceMemoryRegion>(),
  215. true,
  216. )?;
  217. let region = user_reader.read_one_from_user::<PosixKvmUserspaceMemoryRegion>(0)?;
  218. self.kvm
  219. .lock()
  220. .set_memory_region(KvmUserspaceMemoryRegion::from_posix(region)?)?;
  221. return Ok(0);
  222. }
  223. _ => {
  224. // arch_ioctl
  225. }
  226. }
  227. todo!()
  228. }
  229. fn read_at(
  230. &self,
  231. _offset: usize,
  232. _len: usize,
  233. _buf: &mut [u8],
  234. _data: crate::libs::spinlock::SpinLockGuard<crate::filesystem::vfs::FilePrivateData>,
  235. ) -> Result<usize, SystemError> {
  236. todo!()
  237. }
  238. fn write_at(
  239. &self,
  240. _offset: usize,
  241. _len: usize,
  242. _buf: &[u8],
  243. _data: crate::libs::spinlock::SpinLockGuard<crate::filesystem::vfs::FilePrivateData>,
  244. ) -> Result<usize, SystemError> {
  245. todo!()
  246. }
  247. fn fs(&self) -> Arc<dyn crate::filesystem::vfs::FileSystem> {
  248. todo!()
  249. }
  250. fn as_any_ref(&self) -> &dyn core::any::Any {
  251. todo!()
  252. }
  253. fn list(&self) -> Result<alloc::vec::Vec<alloc::string::String>, SystemError> {
  254. todo!()
  255. }
  256. fn metadata(&self) -> Result<Metadata, SystemError> {
  257. Ok(self.metadata.clone())
  258. }
  259. fn close(
  260. &self,
  261. _data: crate::libs::spinlock::SpinLockGuard<crate::filesystem::vfs::FilePrivateData>,
  262. ) -> Result<(), SystemError> {
  263. Ok(())
  264. }
  265. }
  266. #[derive(Debug)]
  267. pub struct KvmVcpuDev {
  268. vcpu: Arc<LockedVirtCpu>,
  269. /// INode 元数据
  270. metadata: Metadata,
  271. }
  272. impl KvmVcpuDev {
  273. const KVM_RUN: u32 = 0xAE80;
  274. const KVM_GET_REGS: u32 = 0x8090AE81;
  275. const KVM_SET_REGS: u32 = 0x4090AE82;
  276. const KVM_GET_SREGS: u32 = 0x8138AE83;
  277. const KVM_SET_SREGS: u32 = 0x4138AE84;
  278. pub fn new(vcpu: Arc<LockedVirtCpu>) -> Arc<Self> {
  279. Arc::new(Self {
  280. vcpu,
  281. metadata: Metadata {
  282. dev_id: 1,
  283. inode_id: generate_inode_id(),
  284. size: 0,
  285. blk_size: 0,
  286. blocks: 0,
  287. atime: PosixTimeSpec::default(),
  288. mtime: PosixTimeSpec::default(),
  289. ctime: PosixTimeSpec::default(),
  290. btime: PosixTimeSpec::default(),
  291. file_type: FileType::KvmDevice, // 文件夹,block设备,char设备
  292. mode: ModeType::S_IALLUGO,
  293. nlinks: 1,
  294. uid: 0,
  295. gid: 0,
  296. raw_dev: DeviceNumber::default(), // 这里用来作为device number
  297. },
  298. })
  299. }
  300. }
  301. impl IndexNode for KvmVcpuDev {
  302. fn open(
  303. &self,
  304. _data: crate::libs::spinlock::SpinLockGuard<crate::filesystem::vfs::FilePrivateData>,
  305. _mode: &FileMode,
  306. ) -> Result<(), SystemError> {
  307. Ok(())
  308. }
  309. fn close(
  310. &self,
  311. _data: crate::libs::spinlock::SpinLockGuard<crate::filesystem::vfs::FilePrivateData>,
  312. ) -> Result<(), SystemError> {
  313. Ok(())
  314. }
  315. fn ioctl(
  316. &self,
  317. cmd: u32,
  318. arg: usize,
  319. _private_data: &crate::filesystem::vfs::FilePrivateData,
  320. ) -> Result<usize, SystemError> {
  321. match cmd {
  322. Self::KVM_RUN => {
  323. if arg != 0 {
  324. return Err(SystemError::EINVAL);
  325. }
  326. let mut vcpu = self.vcpu.lock();
  327. let oldpid = vcpu.pid;
  328. if unlikely(oldpid != Some(ProcessManager::current_pid())) {
  329. vcpu.pid = Some(ProcessManager::current_pid());
  330. }
  331. return vcpu.run();
  332. }
  333. Self::KVM_GET_REGS => {
  334. let kvm_regs = self.vcpu.lock().get_regs();
  335. let mut user_writer = UserBufferWriter::new(
  336. arg as *const KvmCommonRegs as *mut KvmCommonRegs,
  337. core::mem::size_of::<KvmCommonRegs>(),
  338. true,
  339. )?;
  340. user_writer.copy_one_to_user(&kvm_regs, 0)?;
  341. return Ok(0);
  342. }
  343. Self::KVM_SET_REGS => {
  344. let user_reader = UserBufferReader::new(
  345. arg as *const KvmCommonRegs,
  346. core::mem::size_of::<KvmCommonRegs>(),
  347. true,
  348. )?;
  349. let regs = user_reader.read_one_from_user::<KvmCommonRegs>(0)?;
  350. self.vcpu.lock().set_regs(regs)?;
  351. return Ok(0);
  352. }
  353. Self::KVM_GET_SREGS => {
  354. let sregs = self.vcpu.lock().get_segment_regs();
  355. let mut writer = UserBufferWriter::new(
  356. arg as *const UapiKvmSegmentRegs as *mut UapiKvmSegmentRegs,
  357. core::mem::size_of::<UapiKvmSegmentRegs>(),
  358. true,
  359. )?;
  360. writer.copy_one_to_user(&sregs, 0)?;
  361. return Ok(0);
  362. }
  363. Self::KVM_SET_SREGS => {
  364. let user_reader = UserBufferReader::new(
  365. arg as *const UapiKvmSegmentRegs,
  366. core::mem::size_of::<UapiKvmSegmentRegs>(),
  367. true,
  368. )?;
  369. let mut sreg = UapiKvmSegmentRegs::default();
  370. user_reader.copy_one_from_user(&mut sreg, 0)?;
  371. if let Ok(_res) = self.vcpu.lock().set_segment_regs(&mut sreg) {
  372. return Ok(0);
  373. } else {
  374. debug!("set segment regs failed");
  375. return Err(SystemError::EINVAL);
  376. }
  377. }
  378. _ => {
  379. // arch ioctl
  380. warn!("[KVM-VCPU] unknown ioctl cmd {cmd:x}");
  381. }
  382. }
  383. Ok(0)
  384. }
  385. fn metadata(&self) -> Result<Metadata, SystemError> {
  386. Ok(self.metadata.clone())
  387. }
  388. fn read_at(
  389. &self,
  390. _offset: usize,
  391. _len: usize,
  392. _buf: &mut [u8],
  393. _data: crate::libs::spinlock::SpinLockGuard<crate::filesystem::vfs::FilePrivateData>,
  394. ) -> Result<usize, SystemError> {
  395. todo!()
  396. }
  397. fn write_at(
  398. &self,
  399. _offset: usize,
  400. _len: usize,
  401. _buf: &[u8],
  402. _data: crate::libs::spinlock::SpinLockGuard<crate::filesystem::vfs::FilePrivateData>,
  403. ) -> Result<usize, SystemError> {
  404. todo!()
  405. }
  406. fn fs(&self) -> Arc<dyn crate::filesystem::vfs::FileSystem> {
  407. todo!()
  408. }
  409. fn as_any_ref(&self) -> &dyn core::any::Any {
  410. todo!()
  411. }
  412. fn list(&self) -> Result<alloc::vec::Vec<alloc::string::String>, SystemError> {
  413. todo!()
  414. }
  415. }
  416. pub fn kvm_init() -> Result<(), SystemError> {
  417. let kvm_inode = LockedKvmInode::new();
  418. devfs_register("kvm", kvm_inode)?;
  419. Ok(())
  420. }