From 73c607aaddf6e4634cad179a81d3f1bc589f7220 Mon Sep 17 00:00:00 2001 From: YJwu2023 <119829947+YJwu2023@users.noreply.github.com> Date: Sat, 18 Mar 2023 20:43:37 +0800 Subject: [PATCH] =?UTF-8?q?VirtIO=E7=BD=91=E5=8D=A1=E8=83=BD=E5=A4=9F?= =?UTF-8?q?=E6=AD=A3=E5=B8=B8=E5=8F=91=E9=80=81=E3=80=81=E6=8E=A5=E6=94=B6?= =?UTF-8?q?=E6=95=B0=E6=8D=AE=20(#204)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * virtio-net小修改 * 移动volatile.rs到libs文件夹 * 使用virtio-drivers 0.3.0 * bugfix: 初始化BAR之后,未正确设置command register的问题 --------- Co-authored-by: longjin --- kernel/Cargo.toml | 2 +- kernel/src/driver/pci/pci.rs | 35 ++++++++- kernel/src/driver/virtio/mod.rs | 1 - kernel/src/driver/virtio/transport_pci.rs | 56 +++++++++----- kernel/src/driver/virtio/virtio.h | 2 +- kernel/src/driver/virtio/virtio.rs | 35 +++++++-- kernel/src/driver/virtio/virtio_impl.rs | 53 +++++-------- kernel/src/filesystem/devfs/mod.rs | 20 +++-- kernel/src/filesystem/fat/fs.rs | 8 +- kernel/src/libs/mod.rs | 3 +- .../src/{driver/virtio => libs}/volatile.rs | 75 ++++++++++++++++++- kernel/src/libs/volatile_io.rs | 37 --------- tools/run-qemu.sh | 10 +-- 13 files changed, 216 insertions(+), 121 deletions(-) rename kernel/src/{driver/virtio => libs}/volatile.rs (52%) delete mode 100644 kernel/src/libs/volatile_io.rs diff --git a/kernel/Cargo.toml b/kernel/Cargo.toml index e54e01cd..50a3b83a 100644 --- a/kernel/Cargo.toml +++ b/kernel/Cargo.toml @@ -12,7 +12,7 @@ crate-type = ["staticlib"] [dependencies] x86_64 = "0.14.10" bitflags = "1.3.2" -virtio-drivers = "0.2.0" +virtio-drivers = "0.3.0" # 一个无锁MPSC队列 thingbuf = { version = "0.1.3", default-features = false, features = ["alloc"] } # smoltcp 0.9.1 diff --git a/kernel/src/driver/pci/pci.rs b/kernel/src/driver/pci/pci.rs index 6672ba50..0f8ffdc1 100644 --- a/kernel/src/driver/pci/pci.rs +++ b/kernel/src/driver/pci/pci.rs @@ -46,7 +46,7 @@ bitflags! { bitflags! { /// The command register in PCI configuration space. - pub struct Command: u16 { + pub struct CommandRegister: u16 { /// The device can respond to I/O Space accesses. const IO_SPACE = 1 << 0; /// The device can respond to Memory Space accesses. @@ -131,9 +131,10 @@ impl Display for PciError { impl DeviceFunction { /// Returns whether the device and function numbers are valid, i.e. the device is between 0 and /// 31, and the function is between 0 and 7. - ///@brief 检测DeviceFunction实例是否有效 - ///@param self - ///@return bool 是否有效 + /// @brief 检测DeviceFunction实例是否有效 + /// @param self + /// @return bool 是否有效 + #[allow(dead_code)] pub fn valid(&self) -> bool { self.device < 32 && self.function < 8 } @@ -449,6 +450,7 @@ pub struct CapabilityInfo { /// The third and fourth bytes of the capability, to save reading them again. pub private_header: u16, } + /// Iterator over capabilities for a device. /// 创建迭代器以遍历PCI设备的capability #[derive(Debug)] @@ -492,3 +494,28 @@ impl Iterator for CapabilityIterator { }) } } + +/// @brief 设置PCI Config Space里面的Command Register +/// +/// @param device_function 设备 +/// @param value command register要被设置成的值 +pub fn set_command_register(device_function: &DeviceFunction, value: CommandRegister) { + unsafe { + pci_write_config( + device_function.bus, + device_function.device, + device_function.function, + STATUS_COMMAND_OFFSET, + value.bits().into(), + ); + } +} +/// @brief 使能对PCI Memory/IO空间的写入,使能PCI设备作为主设备(主动进行Memory的写入等,msix中断使用到) +/// +/// @param device_function 设备 +pub fn pci_enable_master(device_function: DeviceFunction) { + set_command_register( + &device_function, + CommandRegister::IO_SPACE | CommandRegister::MEMORY_SPACE | CommandRegister::BUS_MASTER, + ); +} diff --git a/kernel/src/driver/virtio/mod.rs b/kernel/src/driver/virtio/mod.rs index ec15e36c..f7b75594 100644 --- a/kernel/src/driver/virtio/mod.rs +++ b/kernel/src/driver/virtio/mod.rs @@ -1,4 +1,3 @@ pub mod transport_pci; pub mod virtio; pub mod virtio_impl; -pub mod volatile; diff --git a/kernel/src/driver/virtio/transport_pci.rs b/kernel/src/driver/virtio/transport_pci.rs index cdd1ad62..162fb459 100644 --- a/kernel/src/driver/virtio/transport_pci.rs +++ b/kernel/src/driver/virtio/transport_pci.rs @@ -1,12 +1,13 @@ //! PCI transport for VirtIO. -use super::volatile::{ - volread, volwrite, ReadOnly, Volatile, VolatileReadable, VolatileWritable, WriteOnly, -}; use crate::driver::pci::pci::{ - capabilities_offset, pci_bar_init, CapabilityIterator, DeviceFunction, PciDeviceBar, PciError, - PCI_CAP_ID_VNDR, + capabilities_offset, pci_bar_init, pci_enable_master, CapabilityIterator, DeviceFunction, + PciDeviceBar, PciError, PCI_CAP_ID_VNDR, }; use crate::include::bindings::bindings::pci_read_config; + +use crate::libs::volatile::{ + volread, volwrite, ReadOnly, Volatile, VolatileReadable, VolatileWritable, WriteOnly, +}; use core::{ fmt::{self, Display, Formatter}, mem::{align_of, size_of}, @@ -14,9 +15,10 @@ use core::{ }; use virtio_drivers::{ transport::{DeviceStatus, DeviceType, Transport}, - Error, Hal, PhysAddr, VirtAddr, + Error, Hal, PhysAddr, }; +type VirtAddr = usize; /// The PCI vendor ID for VirtIO devices. /// PCI Virtio设备的vendor ID const VIRTIO_VENDOR_ID: u16 = 0x1af4; @@ -119,8 +121,9 @@ impl PciTransport { device_function: device_function, next_capability_offset: capabilities_offset(device_function), }; - let device_bar = pci_bar_init(device_function)?; + let device_bar = pci_bar_init(device_function)?; + pci_enable_master(device_function); for capability in device_capability { if capability.id != PCI_CAP_ID_VNDR { continue; @@ -197,6 +200,7 @@ impl PciTransport { notify_off_multiplier, )); } + //kdebug!("notify.offset={},notify.length={}",notify_cfg.offset,notify_cfg.length); let notify_region = get_bar_region_slice::<_>(&device_bar, ¬ify_cfg)?; let isr_status = get_bar_region::<_>( &device_bar, @@ -282,7 +286,9 @@ impl Transport for PciTransport { fn set_guest_page_size(&mut self, _guest_page_size: u32) { // No-op, the PCI transport doesn't care. } - + fn requires_legacy_layout(&self) -> bool { + false + } fn queue_set( &mut self, queue: u16, @@ -293,6 +299,10 @@ impl Transport for PciTransport { ) { // Safe because the common config pointer is valid and we checked in get_bar_region that it // was aligned. + // kdebug!("queue_select={}",queue); + // kdebug!("queue_size={}",size as u16); + // kdebug!("queue_desc={:#x}",descriptors as u64); + // kdebug!("driver_area={:#x}",driver_area); unsafe { volwrite!(self.common_cfg, queue_select, queue); volwrite!(self.common_cfg, queue_size, size as u16); @@ -307,7 +317,6 @@ impl Transport for PciTransport { // Safe because the common config pointer is valid and we checked in get_bar_region that it // was aligned. unsafe { - volwrite!(self.common_cfg, queue_enable, 0); volwrite!(self.common_cfg, queue_select, queue); volwrite!(self.common_cfg, queue_size, 0); volwrite!(self.common_cfg, queue_desc, 0); @@ -355,8 +364,13 @@ impl Transport for PciTransport { } } -/// `virtio_pci_common_cfg`, see 4.1.4.3 "Common configuration structure layout". -/// +impl Drop for PciTransport { + fn drop(&mut self) { + // Reset the device when the transport is dropped. + self.set_status(DeviceStatus::empty()) + } +} + #[repr(C)] struct CommonCfg { device_feature_select: Volatile, @@ -488,6 +502,7 @@ fn get_bar_region( { return Err(VirtioPciError::BarOffsetOutOfRange); } + //kdebug!("Chossed bar ={},used={}",struct_info.bar,struct_info.offset + struct_info.length); let vaddr = (bar_info .virtual_address() .ok_or(VirtioPciError::BarGetVaddrFailed)?) as usize @@ -498,18 +513,25 @@ fn get_bar_region( alignment: align_of::(), }); } - Ok(NonNull::new((vaddr) as _).unwrap()) + let vaddr = NonNull::new(vaddr as *mut u8).unwrap(); + Ok(vaddr.cast()) } -///@brief 获取虚拟地址并将其转化为对应类型的指针 -///@param device_bar 存储bar信息的结构体 struct_info 存储cfg空间的位置信息 +///@brief 获取虚拟地址并将其转化为对应类型的 +///@param device_bar 存储bar信息的结构体 struct_info 存储cfg空间的位置信息切片的指针 ///@return Result, VirtioPciError> 成功则返回对应类型的指针切片,失败则返回Error fn get_bar_region_slice( device_bar: &PciDeviceBar, struct_info: &VirtioCapabilityInfo, ) -> Result, VirtioPciError> { let ptr = get_bar_region::(device_bar, struct_info)?; - let raw_slice = - ptr::slice_from_raw_parts_mut(ptr.as_ptr(), struct_info.length as usize / size_of::()); - Ok(NonNull::new(raw_slice).unwrap()) + // let raw_slice = + // ptr::slice_from_raw_parts_mut(ptr.as_ptr(), struct_info.length as usize / size_of::()); + Ok(nonnull_slice_from_raw_parts( + ptr, + struct_info.length as usize / size_of::(), + )) +} +fn nonnull_slice_from_raw_parts(data: NonNull, len: usize) -> NonNull<[T]> { + NonNull::new(ptr::slice_from_raw_parts_mut(data.as_ptr(), len)).unwrap() } diff --git a/kernel/src/driver/virtio/virtio.h b/kernel/src/driver/virtio/virtio.h index 1798d212..7dc9d54d 100644 --- a/kernel/src/driver/virtio/virtio.h +++ b/kernel/src/driver/virtio/virtio.h @@ -9,4 +9,4 @@ // 获取virtio-net 设备 uint8_t get_virtio_net_device(uint8_t * bus, uint8_t *device,uint8_t * function); //寻找并加载所有virtio设备的驱动(目前只有virtio-net,但其他virtio设备后续也可添加) -extern void c_virtio_probe(); +void c_virtio_probe(); diff --git a/kernel/src/driver/virtio/virtio.rs b/kernel/src/driver/virtio/virtio.rs index 6f81014a..b9e66794 100644 --- a/kernel/src/driver/virtio/virtio.rs +++ b/kernel/src/driver/virtio/virtio.rs @@ -90,18 +90,41 @@ fn virtio_net(transport: T) { return; } }; - // let mut buf = [0u8; 0x100]; + let mut buf = [0u8; 0x100]; // let len = match driver_net.recv(&mut buf) // { // Ok(len) =>{len}, // Err(_) =>{kerror!("virtio_net recv failed");return;} // }; - // kdebug!("recv: {:?}", &buf[..len]); - // match driver_net.send(&buf[..len]) - // { - // Ok(_) =>{kdebug!("virtio_net send success");}, - // Err(_) =>{kerror!("virtio_net send failed");return;}, + match driver_net.can_send() { + true => { + kdebug!("Virtio-net can send"); + } + false => { + kdebug!("Virtio-net can not send"); + } + } + // match driver_net.can_recv() { + // true => { + // kdebug!("can recv") + // } + // false => { + // kdebug!("can not recv"); + // } // } + + let len = 100; + //kdebug!("recv: {:?}", &buf[..len]); + match driver_net.send(&buf[..len]) { + Ok(_) => { + kdebug!("virtio_net send success"); + } + Err(_) => { + kerror!("virtio_net send failed"); + return; + } + } + let mac = driver_net.mac(); kdebug!("virtio_net MAC={:?}", mac); kdebug!("virtio-net test finished"); diff --git a/kernel/src/driver/virtio/virtio_impl.rs b/kernel/src/driver/virtio/virtio_impl.rs index 0032148b..16a48c2d 100644 --- a/kernel/src/driver/virtio/virtio_impl.rs +++ b/kernel/src/driver/virtio/virtio_impl.rs @@ -1,63 +1,57 @@ +/// 为virtio-drivers库提供的操作系统接口 use crate::include::bindings::bindings::{ alloc_pages, free_pages, memory_management_struct, Page, PAGE_2M_SHIFT, PAGE_2M_SIZE, PAGE_OFFSET, PAGE_SHARED, ZONE_NORMAL, }; +use crate::mm::virt_2_phys; use core::mem::size_of; use core::ptr::NonNull; -use virtio_drivers::{BufferDirection, Hal, PhysAddr, VirtAddr, PAGE_SIZE}; - +use virtio_drivers::{BufferDirection, Hal, PhysAddr, PAGE_SIZE}; pub struct HalImpl; impl Hal for HalImpl { /// @brief 申请用于DMA的内存页 /// @param pages 页数(4k一页) /// @return PhysAddr 获得的内存页的初始物理地址 - fn dma_alloc(pages: usize) -> PhysAddr { - let reminder = pages * PAGE_SIZE % (PAGE_2M_SIZE as usize); - let page_num = if reminder > 0 { - (pages * PAGE_SIZE / (PAGE_2M_SIZE as usize) + 1) as i32 - } else { - (pages * PAGE_SIZE / (PAGE_2M_SIZE as usize)) as i32 - }; - + fn dma_alloc(pages: usize, _direction: BufferDirection) -> (PhysAddr, NonNull) { + let page_num = (pages * PAGE_SIZE - 1 + PAGE_2M_SIZE as usize) / PAGE_2M_SIZE as usize; unsafe { - let pa = alloc_pages(ZONE_NORMAL, page_num, PAGE_SHARED as u64); + let pa = alloc_pages(ZONE_NORMAL, page_num as i32, PAGE_SHARED as u64); let page = *pa; - //kdebug!("alloc pages num:{},Phyaddr={}",page_num,page.addr_phys); - return page.addr_phys as PhysAddr; + //kdebug!("alloc pages num:{},Phyaddr={:#x}",pages,page.addr_phys); + ( + page.addr_phys as PhysAddr, + NonNull::new((page.addr_phys as PhysAddr + PAGE_OFFSET as usize) as _).unwrap(), + ) } } /// @brief 释放用于DMA的内存页 /// @param paddr 起始物理地址 pages 页数(4k一页) /// @return i32 0表示成功 - fn dma_dealloc(paddr: PhysAddr, pages: usize) -> i32 { - let reminder = pages * PAGE_SIZE % (PAGE_2M_SIZE as usize); - let page_num = if reminder > 0 { - (pages * PAGE_SIZE / (PAGE_2M_SIZE as usize) + 1) as i32 - } else { - (pages * PAGE_SIZE / (PAGE_2M_SIZE as usize)) as i32 - }; + fn dma_dealloc(paddr: PhysAddr, _vaddr: NonNull, pages: usize) -> i32 { + let page_num = (pages * PAGE_SIZE - 1 + PAGE_2M_SIZE as usize) / PAGE_2M_SIZE as usize; unsafe { let pa = (memory_management_struct.pages_struct as usize + (paddr >> PAGE_2M_SHIFT) * size_of::()) as *mut Page; //kdebug!("free pages num:{},Phyaddr={}",page_num,paddr); - free_pages(pa, page_num); + free_pages(pa, page_num as i32); } return 0; } - /// @brief 物理地址转换为虚拟地址 + /// @brief mmio物理地址转换为虚拟地址,不需要使用 /// @param paddr 起始物理地址 - /// @return VirtAddr 虚拟地址 - fn phys_to_virt(paddr: PhysAddr) -> VirtAddr { - paddr + PAGE_OFFSET as usize + /// @return NonNull 虚拟地址的指针 + fn mmio_phys_to_virt(_paddr: PhysAddr, _size: usize) -> NonNull { + NonNull::new((0) as _).unwrap() } /// @brief 与真实物理设备共享 /// @param buffer 要共享的buffer _direction:设备到driver或driver到设备 /// @return buffer在内存中的物理地址 fn share(buffer: NonNull<[u8]>, _direction: BufferDirection) -> PhysAddr { let vaddr = buffer.as_ptr() as *mut u8 as usize; + //kdebug!("virt:{:x}", vaddr); // Nothing to do, as the host already has access to all memory. - virt_to_phys(vaddr) + virt_2_phys(vaddr) } /// @brief 停止共享(让主机可以访问全部内存的话什么都不用做) fn unshare(_paddr: PhysAddr, _buffer: NonNull<[u8]>, _direction: BufferDirection) { @@ -65,10 +59,3 @@ impl Hal for HalImpl { // anywhere else. } } - -/// @brief 虚拟地址转换为物理地址 -/// @param vaddr 虚拟地址 -/// @return PhysAddr 物理地址 -fn virt_to_phys(vaddr: VirtAddr) -> PhysAddr { - vaddr - PAGE_OFFSET as usize -} diff --git a/kernel/src/filesystem/devfs/mod.rs b/kernel/src/filesystem/devfs/mod.rs index c83bdeb6..655db20d 100644 --- a/kernel/src/filesystem/devfs/mod.rs +++ b/kernel/src/filesystem/devfs/mod.rs @@ -4,11 +4,12 @@ pub mod zero_dev; use super::vfs::{ core::{generate_inode_id, ROOT_INODE}, - FileSystem, FileType, FsInfo, IndexNode, Metadata, PollStatus, file::FileMode, + file::FileMode, + FileSystem, FileType, FsInfo, IndexNode, Metadata, PollStatus, }; use crate::{ include::bindings::bindings::{EEXIST, EISDIR, ENOENT, ENOTDIR, ENOTSUP}, - kdebug, kerror, + kerror, libs::spinlock::{SpinLock, SpinLockGuard}, time::TimeSpec, }; @@ -231,7 +232,7 @@ impl DevFSInode { impl LockedDevFSInode { pub fn add_dir(&self, name: &str) -> Result<(), i32> { - let guard:SpinLockGuard = self.0.lock(); + let guard: SpinLockGuard = self.0.lock(); if guard.children.contains_key(name) { return Err(-(EEXIST as i32)); @@ -270,10 +271,14 @@ impl LockedDevFSInode { return Ok(()); } - fn do_create_with_data(&self, mut guard: SpinLockGuard,_name: &str, + fn do_create_with_data( + &self, + mut guard: SpinLockGuard, + _name: &str, _file_type: FileType, _mode: u32, - _data: usize,) -> Result, i32>{ + _data: usize, + ) -> Result, i32> { if guard.metadata.file_type != FileType::Dir { return Err(-(ENOTDIR as i32)); } @@ -313,7 +318,6 @@ impl LockedDevFSInode { // 将子inode插入父inode的B树中 guard.children.insert(String::from(_name), result.clone()); return Ok(result); - } } @@ -329,7 +333,7 @@ impl IndexNode for LockedDevFSInode { fn close(&self, _data: &mut super::vfs::FilePrivateData) -> Result<(), i32> { return Ok(()); } - + fn create_with_data( &self, name: &str, @@ -338,7 +342,7 @@ impl IndexNode for LockedDevFSInode { data: usize, ) -> Result, i32> { // 获取当前inode - let guard:SpinLockGuard = self.0.lock(); + let guard: SpinLockGuard = self.0.lock(); // 如果当前inode不是文件夹,则返回 return self.do_create_with_data(guard, name, file_type, mode, data); } diff --git a/kernel/src/filesystem/fat/fs.rs b/kernel/src/filesystem/fat/fs.rs index 2546e514..8e47dd4d 100644 --- a/kernel/src/filesystem/fat/fs.rs +++ b/kernel/src/filesystem/fat/fs.rs @@ -10,14 +10,15 @@ use alloc::{ use crate::{ filesystem::vfs::{ - core::generate_inode_id, file::{FilePrivateData, FileMode}, FileSystem, FileType, IndexNode, InodeId, - Metadata, PollStatus, + core::generate_inode_id, + file::{FileMode, FilePrivateData}, + FileSystem, FileType, IndexNode, InodeId, Metadata, PollStatus, }, include::bindings::bindings::{ EFAULT, EINVAL, EISDIR, ENOENT, ENOSPC, ENOTDIR, ENOTEMPTY, ENOTSUP, EPERM, EROFS, }, io::{device::LBA_SIZE, disk_info::Partition, SeekFrom}, - kdebug, kerror, + kerror, libs::{ spinlock::{SpinLock, SpinLockGuard}, vec_cursor::VecCursor, @@ -1539,7 +1540,6 @@ impl IndexNode for LockedFATInode { let r = dir.remove(guard.fs.upgrade().unwrap().clone(), name, true); drop(target_guard); return r; - } fn rmdir(&self, name: &str) -> Result<(), i32> { diff --git a/kernel/src/libs/mod.rs b/kernel/src/libs/mod.rs index 8569e0b5..778ff6c6 100644 --- a/kernel/src/libs/mod.rs +++ b/kernel/src/libs/mod.rs @@ -11,5 +11,6 @@ pub mod semaphore; pub mod spinlock; pub mod vec_cursor; #[macro_use] -pub mod volatile_io; +pub mod volatile; pub mod wait_queue; + diff --git a/kernel/src/driver/virtio/volatile.rs b/kernel/src/libs/volatile.rs similarity index 52% rename from kernel/src/driver/virtio/volatile.rs rename to kernel/src/libs/volatile.rs index ff9f095f..2e55e7be 100644 --- a/kernel/src/driver/virtio/volatile.rs +++ b/kernel/src/libs/volatile.rs @@ -1,8 +1,76 @@ -/// An MMIO register which can only be read from. +macro_rules! volatile_read { + ($data: expr) => { + unsafe { core::ptr::read_volatile(core::ptr::addr_of!($data)) } + }; +} + +macro_rules! volatile_write { + ($data: expr, $value: expr) => { + unsafe { core::ptr::write_volatile(core::ptr::addr_of_mut!($data), $value) } + }; +} + +/// @brief: 用于volatile设置某些bits +/// @param val: 设置这些位 +/// @param flag: true表示设置这些位为1; false表示设置这些位为0; +macro_rules! volatile_set_bit { + ($data: expr, $val: expr, $flag: expr) => { + volatile_write!( + $data, + match $flag { + true => core::ptr::read_volatile(core::ptr::addr_of!($data)) | $val, + false => core::ptr::read_volatile(core::ptr::addr_of!($data)) & (!$val), + } + ) + }; +} + +/// @param data: volatile变量 +/// @param bits: 置1的位才有效,表示写这些位 +/// @param val: 要写的值 +/// 比如: 写 x 的 2至8bit, 为 10, 可以这么写 volatile_write_bit(x, (1<<8)-(1<<2), 10<<2); +macro_rules! volatile_write_bit { + ($data: expr, $bits: expr, $val: expr) => { + volatile_set_bit!($data, $bits, false); + volatile_set_bit!($data, ($val) & ($bits), true); + }; +} + +/// 以下代码来自于virtio-drivers 0.2.0 +/// 在对已经MMIO映射对虚拟地址的寄存器的操作中,我们经常遇到有的寄存器是只读或可读写的 +/// 那么我们就可以使用结构体ReadOnly WriteOnly Volatile对其进行区分 +/// 例: +/// #[repr(C)] +/// struct CommonCfg { +/// device_feature_select: Volatile, +/// device_feature: ReadOnly, +/// driver_feature_select: Volatile, +/// driver_feature: Volatile, +/// msix_config: Volatile, +/// num_queues: ReadOnly, +/// device_status: Volatile, +/// config_generation: ReadOnly, +/// queue_select: Volatile, +/// queue_size: Volatile, +/// queue_msix_vector: Volatile, +/// queue_enable: Volatile, +/// queue_notify_off: Volatile, +/// queue_desc: Volatile, +/// queue_driver: Volatile, +/// queue_device: Volatile, +/// } +/// +/// 对CommonCfg里面的某个寄存器进行读写: +/// volwrite!(self.common_cfg, queue_enable, 0); +/// +/// 这样做不仅使代码的可读性提高了,也避免了对只读寄存器进行写入的误操作 + +/// 只读寄存器 #[derive(Default)] #[repr(transparent)] pub struct ReadOnly(T); +#[allow(dead_code)] impl ReadOnly { /// Construct a new instance for testing. pub fn new(value: T) -> Self { @@ -10,16 +78,17 @@ impl ReadOnly { } } -/// An MMIO register which can only be written to. +/// 只写寄存器 #[derive(Default)] #[repr(transparent)] pub struct WriteOnly(T); -/// An MMIO register which may be both read and written. +/// 写读寄存器 #[derive(Default)] #[repr(transparent)] pub struct Volatile(T); +#[allow(dead_code)] impl Volatile { /// Construct a new instance for testing. pub fn new(value: T) -> Self { diff --git a/kernel/src/libs/volatile_io.rs b/kernel/src/libs/volatile_io.rs deleted file mode 100644 index 8f0254e7..00000000 --- a/kernel/src/libs/volatile_io.rs +++ /dev/null @@ -1,37 +0,0 @@ -macro_rules! volatile_read { - ($data: expr) => { - unsafe { core::ptr::read_volatile(core::ptr::addr_of!($data)) } - }; -} - -macro_rules! volatile_write { - ($data: expr, $value: expr) => { - unsafe { core::ptr::write_volatile(core::ptr::addr_of_mut!($data), $value) } - }; -} - -/// @brief: 用于volatile设置某些bits -/// @param val: 设置这些位 -/// @param flag: true表示设置这些位为1; false表示设置这些位为0; -macro_rules! volatile_set_bit { - ($data: expr, $val: expr, $flag: expr) => { - volatile_write!( - $data, - match $flag { - true => core::ptr::read_volatile(core::ptr::addr_of!($data)) | $val, - false => core::ptr::read_volatile(core::ptr::addr_of!($data)) & (!$val), - } - ) - }; -} - -/// @param data: volatile变量 -/// @param bits: 置1的位才有效,表示写这些位 -/// @param val: 要写的值 -/// 比如: 写 x 的 2至8bit, 为 10, 可以这么写 volatile_write_bit(x, (1<<8)-(1<<2), 10<<2); -macro_rules! volatile_write_bit { - ($data: expr, $bits: expr, $val: expr) => { - volatile_set_bit!($data, $bits, false); - volatile_set_bit!($data, ($val) & ($bits), true); - }; -} diff --git a/tools/run-qemu.sh b/tools/run-qemu.sh index 0595479c..e7c1afd6 100644 --- a/tools/run-qemu.sh +++ b/tools/run-qemu.sh @@ -9,7 +9,7 @@ ARCH="x86_64" # 请根据自己的需要,在-d 后方加入所需的trace事件 # 标准的trace events -qemu_trace_std=cpu_reset,guest_errors,exec,cpu +qemu_trace_std=cpu_reset,guest_errors,exec,cpu,trace:virtio* # 调试usb的trace qemu_trace_usb=trace:usb_xhci_reset,trace:usb_xhci_run,trace:usb_xhci_stop,trace:usb_xhci_irq_msi,trace:usb_xhci_irq_msix,trace:usb_xhci_port_reset,trace:msix_write_config,trace:usb_xhci_irq_msix,trace:usb_xhci_irq_msix_use,trace:usb_xhci_irq_msix_unuse,trace:usb_xhci_irq_msi,trace:usb_xhci_* qemu_accel=kvm @@ -29,7 +29,7 @@ QEMU_RTC_CLOCK="clock=host,base=localtime" QEMU_SERIAL="file:../serial_opt.txt" QEMU_DRIVE="id=disk,file=${QEMU_DISK_IMAGE},if=none" -QEMU_DEVICES="-device ahci,id=ahci -device ide-hd,drive=disk,bus=ahci.0 -net nic,model=virtio -usb -device qemu-xhci,id=xhci,p2=8,p3=4 -machine accel=${qemu_accel}" +QEMU_DEVICES="-device ahci,id=ahci -device ide-hd,drive=disk,bus=ahci.0 -nic user,model=virtio -usb -device qemu-xhci,id=xhci,p2=8,p3=4 -machine accel=${qemu_accel}" QEMU_ARGUMENT="-d ${QEMU_DISK_IMAGE} -m ${QEMU_MEMORY} -smp ${QEMU_SMP} -boot order=d -monitor ${QEMU_MONITOR} -d ${qemu_trace_std} " @@ -42,13 +42,13 @@ if [ $flag_can_run -eq 1 ]; then case "$2" in uefi) #uefi启动新增ovmf.fd固件 if [ ${ARCH} == x86_64 ] ;then - ${QEMU} -bios arch/x86_64/efi/OVMF-pure-efi.fd ${QEMU_ARGUMENT} + sudo ${QEMU} -bios arch/x86_64/efi/OVMF-pure-efi.fd ${QEMU_ARGUMENT} elif [ ${ARCH} == i386 ] ;then - ${QEMU} -bios arch/i386/efi/OVMF-pure-efi.fd ${QEMU_ARGUMENT} + sudo ${QEMU} -bios arch/i386/efi/OVMF-pure-efi.fd ${QEMU_ARGUMENT} fi ;; legacy) - ${QEMU} ${QEMU_ARGUMENT} + sudo ${QEMU} ${QEMU_ARGUMENT} ;; esac