123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494 |
- use core::intrinsics::unlikely;
- use alloc::sync::{Arc, Weak};
- use log::{debug, warn};
- use system_error::SystemError;
- use crate::{
- arch::{
- vm::{kvm_host::KvmCommonRegs, uapi::UapiKvmSegmentRegs},
- MMArch,
- },
- driver::base::device::device_number::DeviceNumber,
- filesystem::{
- devfs::{devfs_register, DevFS, DeviceINode},
- vfs::{
- file::{File, FileMode},
- syscall::ModeType,
- vcore::generate_inode_id,
- FileType, IndexNode, Metadata,
- },
- },
- libs::spinlock::SpinLock,
- mm::MemoryManagementArch,
- process::ProcessManager,
- syscall::user_access::{UserBufferReader, UserBufferWriter},
- time::PosixTimeSpec,
- virt::vm::user_api::{KvmUserspaceMemoryRegion, PosixKvmUserspaceMemoryRegion},
- };
- use super::kvm_host::{vcpu::LockedVirtCpu, LockedVm};
- #[derive(Debug)]
- pub struct KvmInode {
- /// 指向自身的弱引用
- self_ref: Weak<LockedKvmInode>,
- /// 指向inode所在的文件系统对象的指针
- fs: Weak<DevFS>,
- /// INode 元数据
- metadata: Metadata,
- }
- #[derive(Debug)]
- pub struct LockedKvmInode {
- inner: SpinLock<KvmInode>,
- }
- impl LockedKvmInode {
- const KVM_CREATE_VM: u32 = 0xAE01;
- const KVM_GET_VCPU_MMAP_SIZE: u32 = 0xAE04;
- pub fn new() -> Arc<Self> {
- let inode = KvmInode {
- self_ref: Weak::default(),
- fs: Weak::default(),
- metadata: Metadata {
- dev_id: 1,
- inode_id: generate_inode_id(),
- size: 0,
- blk_size: 0,
- blocks: 0,
- atime: PosixTimeSpec::default(),
- mtime: PosixTimeSpec::default(),
- ctime: PosixTimeSpec::default(),
- btime: PosixTimeSpec::default(),
- file_type: FileType::KvmDevice, // 文件夹,block设备,char设备
- mode: ModeType::S_IALLUGO,
- nlinks: 1,
- uid: 0,
- gid: 0,
- raw_dev: DeviceNumber::default(), // 这里用来作为device number
- },
- };
- let result = Arc::new(LockedKvmInode {
- inner: SpinLock::new(inode),
- });
- result.inner.lock().self_ref = Arc::downgrade(&result);
- return result;
- }
- fn create_vm(&self, vm_type: usize) -> Result<usize, SystemError> {
- let kvm = LockedVm::create(vm_type)?;
- let instance = KvmInstance::new(kvm);
- let current = ProcessManager::current_pcb();
- let file = File::new(instance, FileMode::O_RDWR)?;
- let fd = current.fd_table().write().alloc_fd(file, None)?;
- return Ok(fd as usize);
- }
- }
- impl DeviceINode for LockedKvmInode {
- fn set_fs(&self, fs: Weak<DevFS>) {
- self.inner.lock().fs = fs;
- }
- }
- impl IndexNode for LockedKvmInode {
- fn open(
- &self,
- _data: crate::libs::spinlock::SpinLockGuard<crate::filesystem::vfs::FilePrivateData>,
- _mode: &FileMode,
- ) -> Result<(), SystemError> {
- Ok(())
- }
- fn read_at(
- &self,
- _offset: usize,
- _len: usize,
- _buf: &mut [u8],
- _data: crate::libs::spinlock::SpinLockGuard<crate::filesystem::vfs::FilePrivateData>,
- ) -> Result<usize, system_error::SystemError> {
- Err(SystemError::ENOSYS)
- }
- fn write_at(
- &self,
- _offset: usize,
- _len: usize,
- _buf: &[u8],
- _data: crate::libs::spinlock::SpinLockGuard<crate::filesystem::vfs::FilePrivateData>,
- ) -> Result<usize, system_error::SystemError> {
- Err(SystemError::ENOSYS)
- }
- fn fs(&self) -> Arc<dyn crate::filesystem::vfs::FileSystem> {
- self.inner.lock().fs.upgrade().unwrap()
- }
- fn as_any_ref(&self) -> &dyn core::any::Any {
- self
- }
- fn list(&self) -> Result<alloc::vec::Vec<alloc::string::String>, system_error::SystemError> {
- Err(SystemError::ENOSYS)
- }
- fn metadata(&self) -> Result<Metadata, system_error::SystemError> {
- Ok(self.inner.lock().metadata.clone())
- }
- fn ioctl(
- &self,
- cmd: u32,
- arg: usize,
- _private_data: &crate::filesystem::vfs::FilePrivateData,
- ) -> Result<usize, SystemError> {
- match cmd {
- Self::KVM_CREATE_VM => {
- let ret = self.create_vm(arg);
- warn!("[KVM]: KVM_CREATE_VM {ret:?}");
- return ret;
- }
- Self::KVM_GET_VCPU_MMAP_SIZE => {
- if arg != 0 {
- return Err(SystemError::EINVAL);
- }
- debug!("[KVM] KVM_GET_VCPU_MMAP_SIZE");
- return Ok(MMArch::PAGE_SIZE);
- }
- _ => {
- // TODO: arch_ioctl
- warn!("[KVM]: unknown iooctl cmd {cmd:x}");
- }
- }
- Ok(0)
- }
- fn close(
- &self,
- _data: crate::libs::spinlock::SpinLockGuard<crate::filesystem::vfs::FilePrivateData>,
- ) -> Result<(), SystemError> {
- Ok(())
- }
- }
- #[derive(Debug)]
- pub struct KvmInstance {
- kvm: Arc<LockedVm>,
- metadata: Metadata,
- }
- impl KvmInstance {
- const KVM_CREATE_VCPU: u32 = 0xAE41;
- const KVM_SET_USER_MEMORY_REGION: u32 = 0x4020AE46;
- pub fn new(vm: Arc<LockedVm>) -> Arc<Self> {
- Arc::new(Self {
- kvm: vm,
- metadata: Metadata {
- dev_id: 1,
- inode_id: generate_inode_id(),
- size: 0,
- blk_size: 0,
- blocks: 0,
- atime: PosixTimeSpec::default(),
- mtime: PosixTimeSpec::default(),
- ctime: PosixTimeSpec::default(),
- btime: PosixTimeSpec::default(),
- file_type: FileType::KvmDevice,
- mode: ModeType::S_IALLUGO,
- nlinks: 1,
- uid: 0,
- gid: 0,
- raw_dev: DeviceNumber::default(), // 这里用来作为device number
- },
- })
- }
- }
- impl IndexNode for KvmInstance {
- fn open(
- &self,
- _data: crate::libs::spinlock::SpinLockGuard<crate::filesystem::vfs::FilePrivateData>,
- _mode: &crate::filesystem::vfs::file::FileMode,
- ) -> Result<(), SystemError> {
- Ok(())
- }
- #[inline(never)]
- fn ioctl(
- &self,
- cmd: u32,
- arg: usize,
- _private_data: &crate::filesystem::vfs::FilePrivateData,
- ) -> Result<usize, SystemError> {
- debug!("kvm instance ioctl cmd {cmd:x}");
- match cmd {
- Self::KVM_CREATE_VCPU => {
- let ret = self.kvm.lock().create_vcpu(arg);
- debug!("[KVM] create vcpu fd {ret:?}");
- return ret;
- }
- Self::KVM_SET_USER_MEMORY_REGION => {
- debug!("[KVM-INSTANCE] KVM_SET_USER_MEMORY_REGION");
- let user_reader = UserBufferReader::new(
- arg as *const PosixKvmUserspaceMemoryRegion,
- core::mem::size_of::<PosixKvmUserspaceMemoryRegion>(),
- true,
- )?;
- let region = user_reader.read_one_from_user::<PosixKvmUserspaceMemoryRegion>(0)?;
- self.kvm
- .lock()
- .set_memory_region(KvmUserspaceMemoryRegion::from_posix(region)?)?;
- return Ok(0);
- }
- _ => {
- // arch_ioctl
- }
- }
- todo!()
- }
- fn read_at(
- &self,
- _offset: usize,
- _len: usize,
- _buf: &mut [u8],
- _data: crate::libs::spinlock::SpinLockGuard<crate::filesystem::vfs::FilePrivateData>,
- ) -> Result<usize, SystemError> {
- todo!()
- }
- fn write_at(
- &self,
- _offset: usize,
- _len: usize,
- _buf: &[u8],
- _data: crate::libs::spinlock::SpinLockGuard<crate::filesystem::vfs::FilePrivateData>,
- ) -> Result<usize, SystemError> {
- todo!()
- }
- fn fs(&self) -> Arc<dyn crate::filesystem::vfs::FileSystem> {
- todo!()
- }
- fn as_any_ref(&self) -> &dyn core::any::Any {
- todo!()
- }
- fn list(&self) -> Result<alloc::vec::Vec<alloc::string::String>, SystemError> {
- todo!()
- }
- fn metadata(&self) -> Result<Metadata, SystemError> {
- Ok(self.metadata.clone())
- }
- fn close(
- &self,
- _data: crate::libs::spinlock::SpinLockGuard<crate::filesystem::vfs::FilePrivateData>,
- ) -> Result<(), SystemError> {
- Ok(())
- }
- }
- #[derive(Debug)]
- pub struct KvmVcpuDev {
- vcpu: Arc<LockedVirtCpu>,
- /// INode 元数据
- metadata: Metadata,
- }
- impl KvmVcpuDev {
- const KVM_RUN: u32 = 0xAE80;
- const KVM_GET_REGS: u32 = 0x8090AE81;
- const KVM_SET_REGS: u32 = 0x4090AE82;
- const KVM_GET_SREGS: u32 = 0x8138AE83;
- const KVM_SET_SREGS: u32 = 0x4138AE84;
- pub fn new(vcpu: Arc<LockedVirtCpu>) -> Arc<Self> {
- Arc::new(Self {
- vcpu,
- metadata: Metadata {
- dev_id: 1,
- inode_id: generate_inode_id(),
- size: 0,
- blk_size: 0,
- blocks: 0,
- atime: PosixTimeSpec::default(),
- mtime: PosixTimeSpec::default(),
- ctime: PosixTimeSpec::default(),
- btime: PosixTimeSpec::default(),
- file_type: FileType::KvmDevice, // 文件夹,block设备,char设备
- mode: ModeType::S_IALLUGO,
- nlinks: 1,
- uid: 0,
- gid: 0,
- raw_dev: DeviceNumber::default(), // 这里用来作为device number
- },
- })
- }
- }
- impl IndexNode for KvmVcpuDev {
- fn open(
- &self,
- _data: crate::libs::spinlock::SpinLockGuard<crate::filesystem::vfs::FilePrivateData>,
- _mode: &FileMode,
- ) -> Result<(), SystemError> {
- Ok(())
- }
- fn close(
- &self,
- _data: crate::libs::spinlock::SpinLockGuard<crate::filesystem::vfs::FilePrivateData>,
- ) -> Result<(), SystemError> {
- Ok(())
- }
- fn ioctl(
- &self,
- cmd: u32,
- arg: usize,
- _private_data: &crate::filesystem::vfs::FilePrivateData,
- ) -> Result<usize, SystemError> {
- match cmd {
- Self::KVM_RUN => {
- if arg != 0 {
- return Err(SystemError::EINVAL);
- }
- let mut vcpu = self.vcpu.lock();
- let oldpid = vcpu.pid;
- if unlikely(oldpid != Some(ProcessManager::current_pid())) {
- vcpu.pid = Some(ProcessManager::current_pid());
- }
- return vcpu.run();
- }
- Self::KVM_GET_REGS => {
- let kvm_regs = self.vcpu.lock().get_regs();
- let mut user_writer = UserBufferWriter::new(
- arg as *const KvmCommonRegs as *mut KvmCommonRegs,
- core::mem::size_of::<KvmCommonRegs>(),
- true,
- )?;
- user_writer.copy_one_to_user(&kvm_regs, 0)?;
- return Ok(0);
- }
- Self::KVM_SET_REGS => {
- let user_reader = UserBufferReader::new(
- arg as *const KvmCommonRegs,
- core::mem::size_of::<KvmCommonRegs>(),
- true,
- )?;
- let regs = user_reader.read_one_from_user::<KvmCommonRegs>(0)?;
- self.vcpu.lock().set_regs(regs)?;
- return Ok(0);
- }
- Self::KVM_GET_SREGS => {
- let sregs = self.vcpu.lock().get_segment_regs();
- let mut writer = UserBufferWriter::new(
- arg as *const UapiKvmSegmentRegs as *mut UapiKvmSegmentRegs,
- core::mem::size_of::<UapiKvmSegmentRegs>(),
- true,
- )?;
- writer.copy_one_to_user(&sregs, 0)?;
- return Ok(0);
- }
- Self::KVM_SET_SREGS => {
- let user_reader = UserBufferReader::new(
- arg as *const UapiKvmSegmentRegs,
- core::mem::size_of::<UapiKvmSegmentRegs>(),
- true,
- )?;
- let mut sreg = UapiKvmSegmentRegs::default();
- user_reader.copy_one_from_user(&mut sreg, 0)?;
- if let Ok(_res) = self.vcpu.lock().set_segment_regs(&mut sreg) {
- return Ok(0);
- } else {
- debug!("set segment regs failed");
- return Err(SystemError::EINVAL);
- }
- }
- _ => {
- // arch ioctl
- warn!("[KVM-VCPU] unknown ioctl cmd {cmd:x}");
- }
- }
- Ok(0)
- }
- fn metadata(&self) -> Result<Metadata, SystemError> {
- Ok(self.metadata.clone())
- }
- fn read_at(
- &self,
- _offset: usize,
- _len: usize,
- _buf: &mut [u8],
- _data: crate::libs::spinlock::SpinLockGuard<crate::filesystem::vfs::FilePrivateData>,
- ) -> Result<usize, SystemError> {
- todo!()
- }
- fn write_at(
- &self,
- _offset: usize,
- _len: usize,
- _buf: &[u8],
- _data: crate::libs::spinlock::SpinLockGuard<crate::filesystem::vfs::FilePrivateData>,
- ) -> Result<usize, SystemError> {
- todo!()
- }
- fn fs(&self) -> Arc<dyn crate::filesystem::vfs::FileSystem> {
- todo!()
- }
- fn as_any_ref(&self) -> &dyn core::any::Any {
- todo!()
- }
- fn list(&self) -> Result<alloc::vec::Vec<alloc::string::String>, SystemError> {
- todo!()
- }
- }
- pub fn kvm_init() -> Result<(), SystemError> {
- let kvm_inode = LockedKvmInode::new();
- devfs_register("kvm", kvm_inode)?;
- Ok(())
- }
|