DragonOS/kernel/src/virt/kvm/vcpu_dev.rs
GnoCiYeH 406099704e
增加epoll机制 (#455)
* ## 增加epoll机制
- 增加epoll机制
- 添加事件等待队列,提升socket性能
- 优化poll,删除不能poll的文件系统中的poll方法

* 添加细节注释

* 修复文件关闭后epoll还持有对应描述符的文件弱引用的bug

* 将EPollEvent设计为POSIX标准

* 修改s到us转换的计算错误
2023-12-25 18:08:12 +08:00

209 lines
6.6 KiB
Rust
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

use crate::arch::kvm::vmx::vcpu::VcpuContextFrame;
use crate::arch::KVMArch;
use crate::filesystem::devfs::DevFS;
use crate::filesystem::vfs::{
core::generate_inode_id, file::FileMode, make_rawdev, FilePrivateData, FileSystem, FileType,
IndexNode, Metadata,
};
use crate::mm::VirtAddr;
use crate::syscall::user_access::copy_from_user;
use crate::virt::kvm::vcpu::Vcpu;
use crate::virt::kvm::vm;
use crate::{filesystem, kdebug};
use crate::{libs::spinlock::SpinLock, syscall::SystemError, time::TimeSpec};
use alloc::{
string::String,
sync::{Arc, Weak},
vec::Vec,
};
// pub const KVM_API_VERSION:u32 = 12;
pub const KVM_RUN: u32 = 0x00;
// pub const KVM_GET_REGS: u32 = 0x01;
pub const KVM_SET_REGS: u32 = 0x02;
// pub const GUEST_STACK_SIZE:usize = 1024;
// pub const HOST_STACK_SIZE:usize = 0x1000 * 6;
/*
* ioctls for /dev/vm fds:
*/
// pub const KVM_CREATE_VCPU: u32 = 0x00;
// pub const KVM_SET_USER_MEMORY_REGION: u32 = 0x01;
// pub const KVM_GET_DIRTY_LOG: u32 = 0x02;
// pub const KVM_IRQFD: u32 = 0x03;
// pub const KVM_IOEVENTFD: u32 = 0x04;
// pub const KVM_IRQ_LINE_STATUS: u32 = 0x05;
// #[derive(Debug)]
// pub struct InodeInfo {
// kvm: Arc<Hypervisor>,
// }
#[derive(Debug)]
pub struct VcpuInode {
/// uuid 暂时不知道有什么用x
// uuid: Uuid,
/// 指向自身的弱引用
self_ref: Weak<LockedVcpuInode>,
/// 指向inode所在的文件系统对象的指针
fs: Weak<DevFS>,
/// INode 元数据
metadata: Metadata,
// fdata: InodeInfo,
}
#[derive(Debug)]
pub struct LockedVcpuInode(SpinLock<VcpuInode>);
impl LockedVcpuInode {
pub fn new() -> Arc<Self> {
let inode = VcpuInode {
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: TimeSpec::default(),
mtime: TimeSpec::default(),
ctime: TimeSpec::default(),
file_type: FileType::KvmDevice, // 文件夹block设备char设备
mode: filesystem::vfs::syscall::ModeType::S_IALLUGO,
nlinks: 1,
uid: 0,
gid: 0,
raw_dev: make_rawdev(1, 4), // 这里用来作为device number
},
// fdata: InodeInfo {
// kvm: kvm,
// },
};
let result = Arc::new(LockedVcpuInode(SpinLock::new(inode)));
result.0.lock().self_ref = Arc::downgrade(&result);
return result;
}
}
impl IndexNode for LockedVcpuInode {
fn as_any_ref(&self) -> &dyn core::any::Any {
self
}
fn open(&self, _data: &mut FilePrivateData, _mode: &FileMode) -> Result<(), SystemError> {
kdebug!("file private data:{:?}", _data);
return Ok(());
}
fn close(&self, _data: &mut FilePrivateData) -> Result<(), SystemError> {
return Ok(());
}
fn metadata(&self) -> Result<Metadata, SystemError> {
return Ok(self.0.lock().metadata.clone());
}
fn fs(&self) -> Arc<dyn FileSystem> {
return self.0.lock().fs.upgrade().unwrap();
}
fn list(&self) -> Result<Vec<String>, SystemError> {
Err(SystemError::EOPNOTSUPP_OR_ENOTSUP)
}
fn set_metadata(&self, metadata: &Metadata) -> Result<(), SystemError> {
let mut inode = self.0.lock();
inode.metadata.atime = metadata.atime;
inode.metadata.mtime = metadata.mtime;
inode.metadata.ctime = metadata.ctime;
inode.metadata.mode = metadata.mode;
inode.metadata.uid = metadata.uid;
inode.metadata.gid = metadata.gid;
return Ok(());
}
/// @brief io control接口
///
/// @param cmd 命令
/// @param data 数据
///
/// @return 成功Ok()
/// 失败Err(错误码)
fn ioctl(&self, cmd: u32, data: usize) -> Result<usize, SystemError> {
match cmd {
0xdeadbeef => {
kdebug!("kvm_cpu ioctl");
Ok(0)
}
KVM_RUN => {
kdebug!("kvm_cpu ioctl");
// let guest_stack = vec![0xCC; GUEST_STACK_SIZE];
// let host_stack = vec![0xCC; HOST_STACK_SIZE];
// let guest_rsp = guest_stack.as_ptr() as u64 + GUEST_STACK_SIZE as u64;
// let host_rsp = (host_stack.as_ptr() as u64) + HOST_STACK_SIZE as u64;
// let hypervisor = Hypervisor::new(1, host_rsp, 0).expect("Cannot create hypervisor");
// let vcpu = VmxVcpu::new(1, Arc::new(Mutex::new(hypervisor)), host_rsp, guest_rsp, guest_code as *const () as u64).expect("Cannot create VcpuData");
// vcpu.virtualize_cpu().expect("Cannot virtualize cpu");
let vcpu = vm(0).unwrap().vcpu[0].clone();
vcpu.lock().virtualize_cpu()?;
KVMArch::kvm_arch_vcpu_ioctl_run(vcpu.as_ref())?;
Ok(0)
}
KVM_SET_REGS => {
let mut kvm_regs = VcpuContextFrame::default();
unsafe {
copy_from_user(
core::slice::from_raw_parts_mut(
(&mut kvm_regs as *mut _) as *mut u8,
core::mem::size_of::<VcpuContextFrame>(),
),
VirtAddr::new(data),
)?;
}
kdebug!(
"rip={:x}, rflags={:x}, rsp={:x}, rax={:x}",
kvm_regs.rip,
kvm_regs.rflags,
kvm_regs.regs[6],
kvm_regs.regs[0],
);
let vcpu = vm(0).unwrap().vcpu[0].clone();
vcpu.lock().set_regs(kvm_regs)?;
Ok(0)
}
_ => {
kdebug!("kvm_cpu ioctl");
Ok(usize::MAX)
}
}
}
/// 读设备 - 应该调用设备的函数读写,而不是通过文件系统读写
fn read_at(
&self,
_offset: usize,
_len: usize,
_buf: &mut [u8],
_data: &mut FilePrivateData,
) -> Result<usize, SystemError> {
Err(SystemError::EOPNOTSUPP_OR_ENOTSUP)
}
/// 写设备 - 应该调用设备的函数读写,而不是通过文件系统读写
fn write_at(
&self,
_offset: usize,
_len: usize,
_buf: &[u8],
_data: &mut FilePrivateData,
) -> Result<usize, SystemError> {
Err(SystemError::EOPNOTSUPP_OR_ENOTSUP)
}
}