diff --git a/Cargo.lock b/Cargo.lock index 60550b45..a0569cea 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -702,6 +702,7 @@ dependencies = [ "component", "jinux-frame", "jinux-pci", + "jinux-rights", "jinux-util", "jinux-virtio", "lazy_static", @@ -717,6 +718,7 @@ dependencies = [ "component", "jinux-frame", "jinux-pci", + "jinux-rights", "jinux-util", "jinux-virtio", "log", @@ -732,6 +734,7 @@ dependencies = [ "bitflags 1.3.2", "component", "jinux-frame", + "jinux-rights", "jinux-util", "lazy_static", "log", @@ -830,10 +833,12 @@ dependencies = [ "int-to-c-enum", "jinux-frame", "jinux-pci", + "jinux-rights", "jinux-util", "log", "pod", "spin 0.9.8", + "typeflags-util", ] [[package]] diff --git a/framework/jinux-frame/src/io_mem.rs b/framework/jinux-frame/src/io_mem.rs index 946cdc1c..8565ce59 100644 --- a/framework/jinux-frame/src/io_mem.rs +++ b/framework/jinux-frame/src/io_mem.rs @@ -3,7 +3,7 @@ use pod::Pod; use spin::Once; use crate::{ - vm::{Paddr, Vaddr, VmIo}, + vm::{HasPaddr, Paddr, Vaddr, VmIo}, Error, }; @@ -60,6 +60,12 @@ impl VmIo for IoMem { } } +impl HasPaddr for IoMem { + fn paddr(&self) -> Paddr { + crate::vm::vaddr_to_paddr(self.virtual_address).unwrap() + } +} + impl IoMem { pub fn new(range: Range) -> Option { if CHECKER.get().unwrap().check(&range) { @@ -72,10 +78,6 @@ impl IoMem { } } - pub fn paddr(&self) -> Paddr { - crate::vm::vaddr_to_paddr(self.virtual_address).unwrap() - } - fn check_range(&self, offset: usize, len: usize) -> crate::Result<()> { let sum = offset.checked_add(len).ok_or(Error::InvalidArgs)?; if sum > self.limit { diff --git a/framework/jinux-frame/src/vm/frame.rs b/framework/jinux-frame/src/vm/frame.rs index 1a53a056..072b74ce 100644 --- a/framework/jinux-frame/src/vm/frame.rs +++ b/framework/jinux-frame/src/vm/frame.rs @@ -6,7 +6,7 @@ use core::{ use crate::{arch::iommu, config::PAGE_SIZE, prelude::*, Error}; -use super::frame_allocator; +use super::{frame_allocator, HasPaddr}; use super::{Paddr, VmIo}; use pod::Pod; @@ -304,6 +304,12 @@ impl Clone for VmFrame { } } +impl HasPaddr for VmFrame { + fn paddr(&self) -> Paddr { + self.start_paddr() + } +} + impl VmFrame { /// Creates a new VmFrame. /// diff --git a/framework/jinux-frame/src/vm/mod.rs b/framework/jinux-frame/src/vm/mod.rs index a6ea1571..dfee10fc 100644 --- a/framework/jinux-frame/src/vm/mod.rs +++ b/framework/jinux-frame/src/vm/mod.rs @@ -32,9 +32,9 @@ use spin::Once; use crate::boot::memory_region::{MemoryRegion, MemoryRegionType}; -/// Convert physical address to virtual address using offset, only available inside jinux-frame -pub(crate) fn paddr_to_vaddr(pa: usize) -> usize { - pa + PHYS_OFFSET +/// Get physical address trait +pub trait HasPaddr { + fn paddr(&self) -> Paddr; } pub fn vaddr_to_paddr(va: Vaddr) -> Option { @@ -50,6 +50,11 @@ pub const fn is_page_aligned(p: usize) -> bool { (p & (PAGE_SIZE - 1)) == 0 } +/// Convert physical address to virtual address using offset, only available inside jinux-frame +pub(crate) fn paddr_to_vaddr(pa: usize) -> usize { + pa + PHYS_OFFSET +} + /// Only available inside jinux-frame pub(crate) static MEMORY_REGIONS: Once> = Once::new(); diff --git a/services/comps/block/src/virtio.rs b/services/comps/block/src/virtio.rs index 45f1cdb1..57548622 100644 --- a/services/comps/block/src/virtio.rs +++ b/services/comps/block/src/virtio.rs @@ -1,8 +1,8 @@ //! Block device based on Virtio -use jinux_frame::trap::TrapFrame; +use jinux_frame::{io_mem::IoMem, trap::TrapFrame}; use jinux_pci::msix::MSIX; -use jinux_util::frame_ptr::InFramePtr; +use jinux_util::safe_ptr::SafePtr; use jinux_virtio::{device::block::device::BLKDevice, PCIVirtioDevice, VirtioPciCommonCfg}; use log::debug; use spin::Mutex; @@ -11,8 +11,8 @@ use crate::{BlockDevice, BLK_COMPONENT}; pub struct VirtioBlockDevice { blk_device: Mutex, - pub common_cfg: InFramePtr, - msix: MSIX, + pub common_cfg: SafePtr, + _msix: MSIX, } impl BlockDevice for VirtioBlockDevice { @@ -48,7 +48,7 @@ impl VirtioBlockDevice { Self { blk_device, common_cfg: virtio_device.common_cfg, - msix: virtio_device.msix, + _msix: virtio_device.msix, } } } diff --git a/services/comps/input/Cargo.toml b/services/comps/input/Cargo.toml index 0f0c3781..addd1ab7 100644 --- a/services/comps/input/Cargo.toml +++ b/services/comps/input/Cargo.toml @@ -12,6 +12,7 @@ jinux-frame = { path = "../../../framework/jinux-frame" } jinux-pci = { path = "../pci" } jinux-virtio = { path = "../virtio" } jinux-util = { path = "../../libs/jinux-util" } +jinux-rights = { path = "../../libs/jinux-rights" } component = { path = "../../libs/comp-sys/component" } virtio-input-decoder = "0.1.4" log = "0.4" diff --git a/services/comps/input/src/lib.rs b/services/comps/input/src/lib.rs index 8f987250..799a292b 100644 --- a/services/comps/input/src/lib.rs +++ b/services/comps/input/src/lib.rs @@ -83,6 +83,7 @@ impl INPUTComponent { } } +#[allow(dead_code)] #[derive(Debug)] enum InputDeviceHandleError { DeviceNotExists, diff --git a/services/comps/input/src/virtio.rs b/services/comps/input/src/virtio.rs index b2aa908f..c982ca49 100644 --- a/services/comps/input/src/virtio.rs +++ b/services/comps/input/src/virtio.rs @@ -1,10 +1,12 @@ //! Input device based on Virtio use alloc::{string::String, sync::Arc, vec::Vec}; +use jinux_frame::io_mem::IoMem; use jinux_frame::offset_of; use jinux_frame::trap::TrapFrame; use jinux_pci::msix::MSIX; -use jinux_util::frame_ptr::InFramePtr; +use jinux_util::field_ptr; +use jinux_util::safe_ptr::SafePtr; use jinux_virtio::device::input::device::InputProp; use jinux_virtio::VirtioPciCommonCfg; use jinux_virtio::{ @@ -18,8 +20,8 @@ use virtio_input_decoder::{DecodeType, Decoder}; use crate::INPUTDevice; pub struct VirtioInputDevice { input_device: InputDevice, - common_cfg: InFramePtr, - msix: Mutex, + _common_cfg: SafePtr, + _msix: Mutex, name: String, callbacks: Mutex>>, } @@ -47,7 +49,7 @@ impl VirtioInputDevice { fn handle_input(frame: &TrapFrame) { debug!("in handle input"); let input_component = crate::INPUT_COMPONENT.get().unwrap(); - input_component.call(frame.trap_num as u8); + input_component.call(frame.trap_num as u8).unwrap(); } fn config_space_change(_: &TrapFrame) { debug!("input device config space change"); @@ -56,8 +58,9 @@ impl VirtioInputDevice { let common_cfg = virtio_device.common_cfg; let mut msix = virtio_device.msix; - let config_msix_vector = - common_cfg.read_at(offset_of!(VirtioPciCommonCfg, config_msix_vector)) as usize; + let config_msix_vector = field_ptr!(&common_cfg, VirtioPciCommonCfg, config_msix_vector) + .read() + .unwrap() as usize; let mut event_irq_number = 0; for i in 0..msix.table_size as usize { @@ -76,8 +79,8 @@ impl VirtioInputDevice { ( Self { input_device, - common_cfg, - msix: Mutex::new(msix), + _common_cfg: common_cfg, + _msix: Mutex::new(msix), name, callbacks: Mutex::new(Vec::new()), }, diff --git a/services/comps/network/Cargo.toml b/services/comps/network/Cargo.toml index a39d84da..89bc4949 100644 --- a/services/comps/network/Cargo.toml +++ b/services/comps/network/Cargo.toml @@ -11,6 +11,7 @@ jinux-frame = { path = "../../../framework/jinux-frame" } jinux-virtio = { path = "../virtio" } jinux-util = { path = "../../libs/jinux-util" } jinux-pci = { path = "../pci" } +jinux-rights = { path = "../../libs/jinux-rights" } spin = "0.9.4" ringbuf = { version = "0.3.2", default-features = false, features = ["alloc"] } log = "0.4" diff --git a/services/comps/network/src/virtio.rs b/services/comps/network/src/virtio.rs index 305e30b6..5aa5c415 100644 --- a/services/comps/network/src/virtio.rs +++ b/services/comps/network/src/virtio.rs @@ -1,8 +1,10 @@ +use jinux_frame::io_mem::IoMem; use jinux_frame::offset_of; use jinux_frame::sync::SpinLock; use jinux_frame::trap::TrapFrame; use jinux_pci::msix::MSIX; -use jinux_util::frame_ptr::InFramePtr; +use jinux_util::field_ptr; +use jinux_util::safe_ptr::SafePtr; use jinux_virtio::device::network::device::{self, EthernetAddr}; use jinux_virtio::PCIVirtioDevice; use jinux_virtio::VirtioPciCommonCfg; @@ -14,7 +16,7 @@ pub struct VirtioNet { /// Network Device device: device::NetworkDevice, /// Own common cfg to avoid other devices access this frame - _common_cfg: InFramePtr, + _common_cfg: SafePtr, _msix: SpinLock, irq_number: u8, } @@ -45,8 +47,9 @@ impl VirtioNet { let common_cfg = virtio_device.common_cfg; let mut msix = virtio_device.msix; - let config_msix_vector = - common_cfg.read_at(offset_of!(VirtioPciCommonCfg, config_msix_vector)) as usize; + let config_msix_vector = field_ptr!(&common_cfg, VirtioPciCommonCfg, config_msix_vector) + .read() + .unwrap() as usize; let mut network_irq_num = 0; for i in 0..msix.table_size as usize { diff --git a/services/comps/pci/Cargo.toml b/services/comps/pci/Cargo.toml index 8976b981..843fdad9 100644 --- a/services/comps/pci/Cargo.toml +++ b/services/comps/pci/Cargo.toml @@ -10,6 +10,7 @@ bitflags = "1.3" spin = "0.9.4" jinux-frame = { path = "../../../framework/jinux-frame" } jinux-util = { path = "../../libs/jinux-util" } +jinux-rights = { path = "../../libs/jinux-rights" } pod = { git = "https://github.com/jinzhao-dev/pod", rev = "71e59ec" } component = { path = "../../libs/comp-sys/component" } log = "0.4" diff --git a/services/comps/pci/src/msix.rs b/services/comps/pci/src/msix.rs index 3014d40e..fea9848b 100644 --- a/services/comps/pci/src/msix.rs +++ b/services/comps/pci/src/msix.rs @@ -1,3 +1,5 @@ +use core::mem::size_of; + use alloc::vec::Vec; use log::debug; use pod::Pod; @@ -6,8 +8,8 @@ use crate::util::{CSpaceAccessMethod, BAR}; use super::capability::msix::CapabilityMSIXData; -use jinux_frame::{bus::pci::PciDeviceLocation, offset_of, trap::IrqAllocateHandle}; -use jinux_util::frame_ptr::InFramePtr; +use jinux_frame::{bus::pci::PciDeviceLocation, io_mem::IoMem, offset_of, trap::IrqAllocateHandle}; +use jinux_util::{field_ptr, safe_ptr::SafePtr}; #[derive(Debug, Default)] pub struct MSIX { @@ -19,7 +21,7 @@ pub struct MSIX { #[derive(Debug)] pub struct MSIXEntry { - pub table_entry: InFramePtr, + pub table_entry: SafePtr, pub irq_handle: IrqAllocateHandle, } @@ -83,22 +85,36 @@ impl MSIX { debug!("command after:{:x}", am.read16(loc, crate::PCI_COMMAND)); let message_control = am.read16(loc, cap_ptr + 2) | 0x8000; am.write16(loc, cap_ptr + 2, message_control); - let mut table_iter: InFramePtr = - InFramePtr::new(table_base_address as usize) - .expect("can not get in frame ptr for msix"); + let mut table_iter: SafePtr = SafePtr::new( + IoMem::new( + table_base_address as usize + ..table_base_address as usize + + (size_of::() * table_size as usize), + ) + .unwrap(), + 0, + ); for _ in 0..table_size { // local APIC address: 0xFEE0_0000 - table_iter.write_at(offset_of!(MSIXTableEntry, msg_addr), 0xFEE0_0000 as u32); - table_iter.write_at(offset_of!(MSIXTableEntry, msg_upper_addr), 0 as u32); + field_ptr!(&table_iter, MSIXTableEntry, msg_addr) + .write(&0xFEE0_0000u32) + .unwrap(); + field_ptr!(&table_iter, MSIXTableEntry, msg_upper_addr) + .write(&0u32) + .unwrap(); // allocate irq number let handle = jinux_frame::trap::allocate_irq().expect("not enough irq"); - table_iter.write_at(offset_of!(MSIXTableEntry, msg_data), handle.num() as u32); - table_iter.write_at(offset_of!(MSIXTableEntry, vector_control), 0 as u32); + field_ptr!(&table_iter, MSIXTableEntry, msg_data) + .write(&(handle.num() as u32)) + .unwrap(); + field_ptr!(&table_iter, MSIXTableEntry, vector_control) + .write(&0u32) + .unwrap(); cap.table.push(MSIXEntry { table_entry: table_iter.clone(), irq_handle: handle, }); - table_iter = table_iter.add(1); + table_iter.add(1); } cap } diff --git a/services/comps/virtio/Cargo.toml b/services/comps/virtio/Cargo.toml index 9d4e9224..251ad0a5 100644 --- a/services/comps/virtio/Cargo.toml +++ b/services/comps/virtio/Cargo.toml @@ -13,6 +13,8 @@ align_ext = { path = "../../../framework/libs/align_ext" } jinux-frame = { path = "../../../framework/jinux-frame" } jinux-pci = { path = "../pci" } jinux-util = { path = "../../libs/jinux-util" } +jinux-rights = { path = "../../libs/jinux-rights" } +typeflags-util = { path = "../../libs/typeflags-util" } pod = { git = "https://github.com/jinzhao-dev/pod", rev = "71e59ec" } component = { path = "../../libs/comp-sys/component" } log = "0.4" diff --git a/services/comps/virtio/src/device/block/device.rs b/services/comps/virtio/src/device/block/device.rs index c721a19b..d5d318ce 100644 --- a/services/comps/virtio/src/device/block/device.rs +++ b/services/comps/virtio/src/device/block/device.rs @@ -1,9 +1,9 @@ use core::hint::spin_loop; use alloc::vec::Vec; -use jinux_frame::offset_of; +use jinux_frame::{io_mem::IoMem, offset_of}; use jinux_pci::{capability::vendor::virtio::CapabilityVirtioData, util::BAR}; -use jinux_util::frame_ptr::InFramePtr; +use jinux_util::{field_ptr, safe_ptr::SafePtr}; use pod::Pod; use crate::{ @@ -17,7 +17,7 @@ use super::{BLKFeatures, VirtioBLKConfig}; #[derive(Debug)] pub struct BLKDevice { - config: InFramePtr, + config: SafePtr, queue: VirtQueue, } @@ -27,13 +27,15 @@ impl BLKDevice { pub(crate) fn new( cap: &CapabilityVirtioData, bars: [Option; 6], - common_cfg: &InFramePtr, + common_cfg: &SafePtr, notify_base_address: usize, notify_off_multiplier: u32, mut msix_vector_left: Vec, ) -> Result { let config = VirtioBLKConfig::new(cap, bars); - let num_queues = common_cfg.read_at(offset_of!(VirtioPciCommonCfg, num_queues)) as u16; + let num_queues = field_ptr!(common_cfg, VirtioPciCommonCfg, num_queues) + .read() + .unwrap(); if num_queues != 1 { return Err(VirtioDeviceError::QueuesAmountDoNotMatch(num_queues, 1)); } diff --git a/services/comps/virtio/src/device/block/mod.rs b/services/comps/virtio/src/device/block/mod.rs index 95752786..04e11c57 100644 --- a/services/comps/virtio/src/device/block/mod.rs +++ b/services/comps/virtio/src/device/block/mod.rs @@ -1,10 +1,13 @@ pub mod device; +use core::mem::size_of; + use bitflags::bitflags; use int_to_c_enum::TryFromInt; +use jinux_frame::io_mem::IoMem; use jinux_pci::capability::vendor::virtio::CapabilityVirtioData; use jinux_pci::util::BAR; -use jinux_util::frame_ptr::InFramePtr; +use jinux_util::safe_ptr::SafePtr; use pod::Pod; pub const BLK_SIZE: usize = 512; @@ -110,15 +113,19 @@ pub struct VirtioBLKTopology { } impl VirtioBLKConfig { - pub(crate) fn new(cap: &CapabilityVirtioData, bars: [Option; 6]) -> InFramePtr { + pub(crate) fn new(cap: &CapabilityVirtioData, bars: [Option; 6]) -> SafePtr { let bar = cap.bar; let offset = cap.offset; match bars[bar as usize].expect("Virtio pci block cfg:bar is none") { - BAR::Memory(address, _, _, _) => InFramePtr::new(address as usize + offset as usize) - .expect("can not get in frame ptr for virtio block config"), - BAR::IO(_, _) => { - panic!("Virtio pci block cfg:bar is IO type") - } + BAR::Memory(address, _, _, _) => SafePtr::new( + IoMem::new( + (address as usize + offset as usize) + ..(address as usize + offset as usize + size_of::()), + ) + .unwrap(), + 0, + ), + BAR::IO(_, _) => panic!("Virtio pci block cfg:bar is IO type"), } } } diff --git a/services/comps/virtio/src/device/input/device.rs b/services/comps/virtio/src/device/input/device.rs index f14cba04..d22b5c7d 100644 --- a/services/comps/virtio/src/device/input/device.rs +++ b/services/comps/virtio/src/device/input/device.rs @@ -1,9 +1,9 @@ use crate::{device::VirtioDeviceError, queue::VirtQueue, VirtioPciCommonCfg}; use alloc::{boxed::Box, vec::Vec}; use bitflags::bitflags; -use jinux_frame::offset_of; +use jinux_frame::{io_mem::IoMem, offset_of}; use jinux_pci::{capability::vendor::virtio::CapabilityVirtioData, util::BAR}; -use jinux_util::frame_ptr::InFramePtr; +use jinux_util::{field_ptr, safe_ptr::SafePtr}; use pod::Pod; use spin::Mutex; @@ -43,7 +43,7 @@ pub const FF_STATUS: u8 = 0x17; /// making pass-through implementations on top of evdev easy. #[derive(Debug)] pub struct InputDevice { - config: InFramePtr, + config: SafePtr, event_queue: Mutex, status_queue: VirtQueue, pub event_buf: Mutex>, @@ -55,7 +55,7 @@ impl InputDevice { pub fn new( cap: &CapabilityVirtioData, bars: [Option; 6], - common_cfg: &InFramePtr, + common_cfg: &SafePtr, notify_base_address: usize, notify_off_multiplier: u32, mut msix_vector_left: Vec, @@ -135,12 +135,18 @@ impl InputDevice { /// Query a specific piece of information by `select` and `subsel`, and write /// result to `out`, return the result size. pub fn query_config_select(&self, select: InputConfigSelect, subsel: u8, out: &mut [u8]) -> u8 { - self.config - .write_at(offset_of!(VirtioInputConfig, select), select as u8); - self.config - .write_at(offset_of!(VirtioInputConfig, subsel), subsel as u8); - let size = self.config.read_at(offset_of!(VirtioInputConfig, size)); - let data: [u8; 128] = self.config.read_at(offset_of!(VirtioInputConfig, data)); + field_ptr!(&self.config, VirtioInputConfig, select) + .write(&(select as u8)) + .unwrap(); + field_ptr!(&self.config, VirtioInputConfig, subsel) + .write(&(subsel as u8)) + .unwrap(); + let size = field_ptr!(&self.config, VirtioInputConfig, size) + .read() + .unwrap(); + let data: [u8; 128] = field_ptr!(&self.config, VirtioInputConfig, data) + .read() + .unwrap(); out[..size as usize].copy_from_slice(&data[..size as usize]); size } diff --git a/services/comps/virtio/src/device/input/mod.rs b/services/comps/virtio/src/device/input/mod.rs index 3ea7d6d0..a801f496 100644 --- a/services/comps/virtio/src/device/input/mod.rs +++ b/services/comps/virtio/src/device/input/mod.rs @@ -25,8 +25,11 @@ // pub mod device; +use core::mem::size_of; + +use jinux_frame::io_mem::IoMem; use jinux_pci::{capability::vendor::virtio::CapabilityVirtioData, util::BAR}; -use jinux_util::frame_ptr::InFramePtr; +use jinux_util::safe_ptr::SafePtr; use pod::Pod; /// Select value used for [`VirtIOInput::query_config_select()`]. @@ -69,15 +72,19 @@ pub struct VirtioInputConfig { } impl VirtioInputConfig { - pub(crate) fn new(cap: &CapabilityVirtioData, bars: [Option; 6]) -> InFramePtr { + pub(crate) fn new(cap: &CapabilityVirtioData, bars: [Option; 6]) -> SafePtr { let bar = cap.bar; let offset = cap.offset; match bars[bar as usize].expect("Virtio pci block cfg:bar is none") { - BAR::Memory(address, _, _, _) => InFramePtr::new(address as usize + offset as usize) - .expect("can not get in frame ptr for virtio block config"), - BAR::IO(_, _) => { - panic!("Virtio pci block cfg:bar is IO type") - } + BAR::Memory(address, _, _, _) => SafePtr::new( + IoMem::new( + (address as usize + offset as usize) + ..(address as usize + offset as usize + size_of::()), + ) + .unwrap(), + 0, + ), + BAR::IO(_, _) => panic!("Virtio pci block cfg:bar is IO type"), } } } diff --git a/services/comps/virtio/src/device/mod.rs b/services/comps/virtio/src/device/mod.rs index cf007e68..6342d86e 100644 --- a/services/comps/virtio/src/device/mod.rs +++ b/services/comps/virtio/src/device/mod.rs @@ -3,11 +3,12 @@ use crate::{ VirtioPciCommonCfg, }; use alloc::vec::Vec; +use jinux_frame::io_mem::IoMem; use jinux_pci::{ capability::{vendor::virtio::CapabilityVirtioData, Capability}, util::BAR, }; -use jinux_util::frame_ptr::InFramePtr; +use jinux_util::safe_ptr::SafePtr; use self::{input::device::InputDevice, network::device::NetworkDevice}; @@ -56,7 +57,7 @@ pub struct VirtioInfo { pub device_type: VirtioDeviceType, pub notify_base_address: u64, pub notify_off_multiplier: u32, - pub common_cfg_frame_ptr: InFramePtr, + pub common_cfg_frame_ptr: SafePtr, pub device_cap_cfg: CapabilityVirtioData, } diff --git a/services/comps/virtio/src/device/network/config.rs b/services/comps/virtio/src/device/network/config.rs index 36356573..870c85eb 100644 --- a/services/comps/virtio/src/device/network/config.rs +++ b/services/comps/virtio/src/device/network/config.rs @@ -1,6 +1,9 @@ +use core::mem::size_of; + use bitflags::bitflags; +use jinux_frame::io_mem::IoMem; use jinux_pci::{capability::vendor::virtio::CapabilityVirtioData, util::BAR}; -use jinux_util::frame_ptr::InFramePtr; +use jinux_util::safe_ptr::SafePtr; use pod::Pod; use super::device::EthernetAddr; @@ -70,12 +73,18 @@ pub struct VirtioNetConfig { } impl VirtioNetConfig { - pub(crate) fn new(cap: &CapabilityVirtioData, bars: [Option; 6]) -> InFramePtr { + pub(crate) fn new(cap: &CapabilityVirtioData, bars: [Option; 6]) -> SafePtr { let bar = cap.bar; let offset = cap.offset; match bars[bar as usize].expect("Virtio pci net cfg:bar is none") { - BAR::Memory(address, _, _, _) => InFramePtr::new(address as usize + offset as usize) - .expect("can not get in frame ptr for virtio net config"), + BAR::Memory(address, _, _, _) => SafePtr::new( + IoMem::new( + (address as usize + offset as usize) + ..(address as usize + offset as usize + size_of::()), + ) + .unwrap(), + 0, + ), BAR::IO(_, _) => panic!("Virtio pci net cfg:bar is IO type"), } } diff --git a/services/comps/virtio/src/device/network/device.rs b/services/comps/virtio/src/device/network/device.rs index 10c36ce2..8cca99bc 100644 --- a/services/comps/virtio/src/device/network/device.rs +++ b/services/comps/virtio/src/device/network/device.rs @@ -1,9 +1,9 @@ use core::hint::spin_loop; use alloc::vec::Vec; -use jinux_frame::offset_of; +use jinux_frame::{io_mem::IoMem, offset_of}; use jinux_pci::{capability::vendor::virtio::CapabilityVirtioData, util::BAR}; -use jinux_util::{frame_ptr::InFramePtr, slot_vec::SlotVec}; +use jinux_util::{field_ptr, safe_ptr::SafePtr, slot_vec::SlotVec}; use log::debug; use pod::Pod; @@ -60,7 +60,7 @@ impl NetworkDevice { pub fn new( cap: &CapabilityVirtioData, bars: [Option; 6], - common_cfg: &InFramePtr, + common_cfg: &SafePtr, notify_base_address: usize, notify_off_multiplier: u32, mut msix_vector_left: Vec, @@ -68,26 +68,30 @@ impl NetworkDevice { let virtio_net_config = VirtioNetConfig::new(cap, bars); let features = { // select low - common_cfg.write_at( - offset_of!(VirtioPciCommonCfg, device_feature_select), - 0 as u32, - ); - let device_feature_low = - common_cfg.read_at(offset_of!(VirtioPciCommonCfg, device_feature)) as u64; + field_ptr!(common_cfg, VirtioPciCommonCfg, device_feature_select) + .write(&0u32) + .unwrap(); + let device_feature_low = field_ptr!(common_cfg, VirtioPciCommonCfg, device_feature) + .read() + .unwrap() as u64; // select high - common_cfg.write_at( - offset_of!(VirtioPciCommonCfg, device_feature_select), - 1 as u32, - ); - let device_feature_high = - common_cfg.read_at(offset_of!(VirtioPciCommonCfg, device_feature)) as u64; + field_ptr!(common_cfg, VirtioPciCommonCfg, device_feature_select) + .write(&1u32) + .unwrap(); + let device_feature_high = field_ptr!(common_cfg, VirtioPciCommonCfg, device_feature) + .read() + .unwrap() as u64; let device_feature = device_feature_high << 32 | device_feature_low; NetworkFeatures::from_bits_truncate(Self::negotiate_features(device_feature)) }; debug!("virtio_net_config = {:?}", virtio_net_config); debug!("features = {:?}", features); - let mac_addr = virtio_net_config.read_at(offset_of!(VirtioNetConfig, mac)); - let status = virtio_net_config.read_at(offset_of!(VirtioNetConfig, status)); + let mac_addr = field_ptr!(&virtio_net_config, VirtioNetConfig, mac) + .read() + .unwrap(); + let status = field_ptr!(&virtio_net_config, VirtioNetConfig, status) + .read() + .unwrap(); debug!("mac addr = {:x?}, status = {:?}", mac_addr, status); let (recv_msix_vec, send_msix_vec) = { if msix_vector_left.len() >= 2 { @@ -132,7 +136,7 @@ impl NetworkDevice { } Ok(Self { - config: virtio_net_config.read(), + config: virtio_net_config.read().unwrap(), mac_addr, send_queue, recv_queue, diff --git a/services/comps/virtio/src/lib.rs b/services/comps/virtio/src/lib.rs index 17d58572..300f02d1 100644 --- a/services/comps/virtio/src/lib.rs +++ b/services/comps/virtio/src/lib.rs @@ -6,15 +6,15 @@ extern crate alloc; use component::init_component; -use core::str::FromStr; +use core::{mem::size_of, str::FromStr}; use alloc::{collections::VecDeque, string::String, sync::Arc, vec::Vec}; use bitflags::bitflags; use component::ComponentInitError; use device::VirtioDevice; -use jinux_frame::{offset_of, trap::TrapFrame}; +use jinux_frame::{io_mem::IoMem, offset_of, trap::TrapFrame}; use jinux_pci::{util::BAR, PciDevice}; -use jinux_util::frame_ptr::InFramePtr; +use jinux_util::{field_ptr, safe_ptr::SafePtr}; use log::{debug, info}; use pod::Pod; use spin::{Mutex, Once}; @@ -76,7 +76,7 @@ impl VIRTIOComponent { let mut devices = Vec::new(); let mut lock = self.virtio_devices.lock(); let len = lock.len(); - for i in 0..len { + for _ in 0..len { let device = lock.pop_front().unwrap(); let d_type = VirtioDeviceType::from_virtio_device(&device.device); if d_type == device_type { @@ -165,14 +165,20 @@ pub struct VirtioPciCommonCfg { } impl VirtioPciCommonCfg { - pub(crate) fn new(cap: &CapabilityVirtioData, bars: [Option; 6]) -> InFramePtr { + pub(crate) fn new(cap: &CapabilityVirtioData, bars: [Option; 6]) -> SafePtr { let bar = cap.bar; let offset = cap.offset; match bars[bar as usize].expect("Virtio pci common cfg:bar is none") { BAR::Memory(address, _, _, _) => { debug!("common_cfg addr:{:x}", (address as usize + offset as usize)); - InFramePtr::new(address as usize + offset as usize) - .expect("cannot get InFramePtr in VitioPciCommonCfg") + SafePtr::new( + IoMem::new( + (address as usize + offset as usize) + ..(address as usize + offset as usize + size_of::()), + ) + .unwrap(), + 0, + ) } BAR::IO(first, second) => { panic!( @@ -219,7 +225,7 @@ impl VirtioDeviceType { pub struct PCIVirtioDevice { /// common config of one device - pub common_cfg: InFramePtr, + pub common_cfg: SafePtr, pub device: VirtioDevice, pub msix: MSIX, } @@ -266,73 +272,70 @@ impl PCIVirtioDevice { let virtio_info = VirtioInfo::new(device_type, bars, virtio_cap_list).unwrap(); let mut msix_vector_list: Vec = (0..msix.table_size).collect(); let config_msix_vector = msix_vector_list.pop().unwrap(); - let common_cfg_frame_ptr = &virtio_info.common_cfg_frame_ptr; + let common_cfg = &virtio_info.common_cfg_frame_ptr; // Reset device - common_cfg_frame_ptr.write_at(offset_of!(VirtioPciCommonCfg, device_status), 0 as u8); + field_ptr!(common_cfg, VirtioPciCommonCfg, device_status) + .write(&0u8) + .unwrap(); - let num_queues: u16 = - common_cfg_frame_ptr.read_at(offset_of!(VirtioPciCommonCfg, num_queues)); - debug!("num_queues:{:x}", num_queues); - // the table size of msix should be equal to n+1 or 2 where n is the virtqueue amount - assert!(msix.table_size == 2 || msix.table_size == (num_queues + 1)); - common_cfg_frame_ptr.write_at( - offset_of!(VirtioPciCommonCfg, config_msix_vector), - config_msix_vector, - ); - common_cfg_frame_ptr.write_at( - offset_of!(VirtioPciCommonCfg, device_status), - (DeviceStatus::ACKNOWLEDGE | DeviceStatus::DRIVER).bits(), - ); + field_ptr!(common_cfg, VirtioPciCommonCfg, config_msix_vector) + .write(&config_msix_vector) + .unwrap(); + field_ptr!(common_cfg, VirtioPciCommonCfg, device_status) + .write(&(DeviceStatus::ACKNOWLEDGE | DeviceStatus::DRIVER).bits()) + .unwrap(); // negotiate features // get the value of device features - common_cfg_frame_ptr.write_at( - offset_of!(VirtioPciCommonCfg, device_feature_select), - 0 as u32, - ); - let mut low: u32 = - common_cfg_frame_ptr.read_at(offset_of!(VirtioPciCommonCfg, device_feature)); - common_cfg_frame_ptr.write_at( - offset_of!(VirtioPciCommonCfg, device_feature_select), - 1 as u32, - ); - let mut high: u32 = - common_cfg_frame_ptr.read_at(offset_of!(VirtioPciCommonCfg, device_feature)); + field_ptr!(common_cfg, VirtioPciCommonCfg, device_feature_select) + .write(&0u32) + .unwrap(); + let mut low: u32 = field_ptr!(common_cfg, VirtioPciCommonCfg, device_feature) + .read() + .unwrap(); + field_ptr!(common_cfg, VirtioPciCommonCfg, device_feature_select) + .write(&1u32) + .unwrap(); + let mut high: u32 = field_ptr!(common_cfg, VirtioPciCommonCfg, device_feature) + .read() + .unwrap(); let mut feature = (high as u64) << 32; feature |= low as u64; // let the device to negotiate Features let driver_features = VirtioDevice::negotiate_features(feature, device_type); - debug!("support_features:{:x}", driver_features); // write features back low = driver_features as u32; high = (driver_features >> 32) as u32; - common_cfg_frame_ptr.write_at( - offset_of!(VirtioPciCommonCfg, driver_feature_select), - 0 as u32, - ); - common_cfg_frame_ptr.write_at(offset_of!(VirtioPciCommonCfg, driver_feature), low); - common_cfg_frame_ptr.write_at( - offset_of!(VirtioPciCommonCfg, driver_feature_select), - 1 as u32, - ); - common_cfg_frame_ptr.write_at(offset_of!(VirtioPciCommonCfg, driver_feature), high); - + field_ptr!(common_cfg, VirtioPciCommonCfg, driver_feature_select) + .write(&0u32) + .unwrap(); + field_ptr!(common_cfg, VirtioPciCommonCfg, driver_feature) + .write(&low) + .unwrap(); + field_ptr!(common_cfg, VirtioPciCommonCfg, driver_feature_select) + .write(&1u32) + .unwrap(); + field_ptr!(common_cfg, VirtioPciCommonCfg, driver_feature) + .write(&high) + .unwrap(); // change to features ok status - common_cfg_frame_ptr.write_at( - offset_of!(VirtioPciCommonCfg, device_status), - (DeviceStatus::ACKNOWLEDGE | DeviceStatus::DRIVER | DeviceStatus::FEATURES_OK).bits(), - ); + field_ptr!(common_cfg, VirtioPciCommonCfg, device_status) + .write( + &(DeviceStatus::ACKNOWLEDGE | DeviceStatus::DRIVER | DeviceStatus::FEATURES_OK) + .bits(), + ) + .unwrap(); let device = VirtioDevice::new(&virtio_info, bars, msix_vector_list).unwrap(); - // change to driver ok status - common_cfg_frame_ptr.write_at( - offset_of!(VirtioPciCommonCfg, device_status), - (DeviceStatus::ACKNOWLEDGE - | DeviceStatus::DRIVER - | DeviceStatus::FEATURES_OK - | DeviceStatus::DRIVER_OK) - .bits(), - ); + field_ptr!(common_cfg, VirtioPciCommonCfg, device_status) + .write( + &(DeviceStatus::ACKNOWLEDGE + | DeviceStatus::DRIVER + | DeviceStatus::FEATURES_OK + | DeviceStatus::DRIVER_OK) + .bits(), + ) + .unwrap(); Self { common_cfg: virtio_info.common_cfg_frame_ptr, device, @@ -350,8 +353,9 @@ impl PCIVirtioDevice { T: Fn(&TrapFrame) + Send + Sync + 'static, { let config_msix_vector = - self.common_cfg - .read_at(offset_of!(VirtioPciCommonCfg, config_msix_vector)) as usize; + field_ptr!(&self.common_cfg, VirtioPciCommonCfg, config_msix_vector) + .read() + .unwrap() as usize; for i in 0..self.msix.table_size as usize { let msix = self.msix.table.get_mut(i).unwrap(); if !msix.irq_handle.is_empty() { diff --git a/services/comps/virtio/src/queue.rs b/services/comps/virtio/src/queue.rs index 0e1a4958..a0cc3219 100644 --- a/services/comps/virtio/src/queue.rs +++ b/services/comps/virtio/src/queue.rs @@ -3,12 +3,17 @@ use super::VirtioPciCommonCfg; use alloc::vec::Vec; use bitflags::bitflags; -use core::sync::atomic::{fence, Ordering}; -use jinux_frame::{ - offset_of, - vm::{VmAllocOptions, VmFrameVec}, +use core::{ + mem::size_of, + sync::atomic::{fence, Ordering}, }; -use jinux_util::frame_ptr::InFramePtr; +use jinux_frame::{ + io_mem::IoMem, + offset_of, + vm::{VmAllocOptions, VmFrame, VmFrameVec}, +}; +use jinux_rights::{Dup, TRightSet, TRights, Write}; +use jinux_util::{field_ptr, safe_ptr::SafePtr}; use log::debug; use pod::Pod; @@ -27,13 +32,13 @@ pub enum QueueError { #[derive(Debug)] pub struct VirtQueue { /// Descriptor table - descs: Vec>, + descs: Vec>, /// Available ring - avail: InFramePtr, + avail: SafePtr, /// Used ring - used: InFramePtr, + used: SafePtr, /// point to notify address - notify: InFramePtr, + notify: SafePtr, /// The index of queue queue_idx: u32, @@ -55,89 +60,97 @@ pub struct VirtQueue { impl VirtQueue { /// Create a new VirtQueue. pub(crate) fn new( - cfg: &InFramePtr, + cfg: &SafePtr, idx: usize, size: u16, notify_base_address: usize, notify_off_multiplier: u32, msix_vector: u16, ) -> Result { - cfg.write_at(offset_of!(VirtioPciCommonCfg, queue_select), idx as u16); + field_ptr!(cfg, VirtioPciCommonCfg, queue_select) + .write(&(idx as u16)) + .unwrap(); assert_eq!( - cfg.read_at(offset_of!(VirtioPciCommonCfg, queue_select)), + field_ptr!(cfg, VirtioPciCommonCfg, queue_select) + .read() + .unwrap(), idx as u16 ); if !size.is_power_of_two() { return Err(QueueError::InvalidArgs); } - - cfg.write_at(offset_of!(VirtioPciCommonCfg, queue_size), size); - cfg.write_at( - offset_of!(VirtioPciCommonCfg, queue_msix_vector), - msix_vector, - ); + field_ptr!(cfg, VirtioPciCommonCfg, queue_size) + .write(&size) + .unwrap(); + field_ptr!(cfg, VirtioPciCommonCfg, queue_msix_vector) + .write(&msix_vector) + .unwrap(); assert_eq!( - cfg.read_at(offset_of!(VirtioPciCommonCfg, queue_msix_vector)), + field_ptr!(cfg, VirtioPciCommonCfg, queue_msix_vector) + .read() + .unwrap(), msix_vector ); - //allocate page - - let desc_frame_ptr: InFramePtr = InFramePtr::new_with_vm_frame( + let desc_frame_ptr: SafePtr = SafePtr::new( VmFrameVec::allocate(&VmAllocOptions::new(1).uninit(false).can_dma(true)) .unwrap() .pop() .unwrap(), - ) - .unwrap(); - let avail_frame_ptr: InFramePtr = InFramePtr::new_with_vm_frame( + 0, + ); + let avail_frame_ptr: SafePtr = SafePtr::new( VmFrameVec::allocate(&VmAllocOptions::new(1).uninit(false).can_dma(true)) .unwrap() .pop() .unwrap(), - ) - .unwrap(); - let used_frame_ptr: InFramePtr = InFramePtr::new_with_vm_frame( + 0, + ); + let used_frame_ptr: SafePtr = SafePtr::new( VmFrameVec::allocate(&VmAllocOptions::new(1).uninit(false).can_dma(true)) .unwrap() .pop() .unwrap(), - ) - .unwrap(); + 0, + ); debug!("queue_desc start paddr:{:x?}", desc_frame_ptr.paddr()); debug!("queue_driver start paddr:{:x?}", avail_frame_ptr.paddr()); debug!("queue_device start paddr:{:x?}", used_frame_ptr.paddr()); - - cfg.write_at( - offset_of!(VirtioPciCommonCfg, queue_desc), - desc_frame_ptr.paddr() as u64, - ); - - cfg.write_at( - offset_of!(VirtioPciCommonCfg, queue_driver), - avail_frame_ptr.paddr() as u64, - ); - - cfg.write_at( - offset_of!(VirtioPciCommonCfg, queue_device), - used_frame_ptr.paddr() as u64, - ); + field_ptr!(cfg, VirtioPciCommonCfg, queue_desc) + .write(&(desc_frame_ptr.paddr() as u64)) + .unwrap(); + field_ptr!(cfg, VirtioPciCommonCfg, queue_driver) + .write(&(avail_frame_ptr.paddr() as u64)) + .unwrap(); + field_ptr!(cfg, VirtioPciCommonCfg, queue_device) + .write(&(used_frame_ptr.paddr() as u64)) + .unwrap(); let mut descs = Vec::with_capacity(size as usize); descs.push(desc_frame_ptr); for i in 0..size as usize { - descs.push(descs.get(i).unwrap().add(1)) + let mut desc = descs.get(i).unwrap().clone(); + desc.offset(1); + descs.push(desc); } - - let notify = InFramePtr::new(notify_base_address + notify_off_multiplier as usize * idx) - .expect("can not get Inframeptr for virtio queue notify"); + let notify_address = notify_base_address + notify_off_multiplier as usize * idx; + let notify = SafePtr::new( + IoMem::new(notify_address..notify_address + size_of::()).unwrap(), + 0, + ); // Link descriptors together. for i in 0..(size - 1) { let temp = descs.get(i as usize).unwrap(); - temp.write_at(offset_of!(Descriptor, next), i + 1); + field_ptr!(temp, Descriptor, next) + .write(&(i + 1)) + .map_err(|_err| QueueError::InvalidArgs)?; } - avail_frame_ptr.write_at(offset_of!(AvailRing, flags), 0 as u16); - cfg.write_at(offset_of!(VirtioPciCommonCfg, queue_enable), 1 as u16); + field_ptr!(&avail_frame_ptr, AvailRing, flags) + .write(&(0u16)) + .map_err(|_err| QueueError::InvalidArgs)?; + field_ptr!(cfg, VirtioPciCommonCfg, queue_enable) + .write(&1u16) + .unwrap(); Ok(VirtQueue { descs, avail: avail_frame_ptr, @@ -168,44 +181,46 @@ impl VirtQueue { let mut last = self.free_head; for input in inputs.iter() { let desc = &self.descs[self.free_head as usize]; - set_buf(desc, input); - desc.write_at(offset_of!(Descriptor, flags), DescFlags::NEXT); + set_buf(&desc.borrow_vm().restrict::(), input); + field_ptr!(desc, Descriptor, flags) + .write(&DescFlags::NEXT) + .unwrap(); last = self.free_head; - self.free_head = desc.read_at(offset_of!(Descriptor, next)); + self.free_head = field_ptr!(desc, Descriptor, next).read().unwrap(); } for output in outputs.iter() { let desc = &mut self.descs[self.free_head as usize]; - set_buf(desc, output); - desc.write_at( - offset_of!(Descriptor, flags), - DescFlags::NEXT | DescFlags::WRITE, - ); + set_buf(&desc.borrow_vm().restrict::(), output); + field_ptr!(desc, Descriptor, flags) + .write(&(DescFlags::NEXT | DescFlags::WRITE)) + .unwrap(); last = self.free_head; - self.free_head = desc.read_at(offset_of!(Descriptor, next)); + self.free_head = field_ptr!(desc, Descriptor, next).read().unwrap(); } // set last_elem.next = NULL { let desc = &mut self.descs[last as usize]; - let mut flags: DescFlags = desc.read_at(offset_of!(Descriptor, flags)); + let mut flags: DescFlags = field_ptr!(desc, Descriptor, flags).read().unwrap(); flags.remove(DescFlags::NEXT); - desc.write_at(offset_of!(Descriptor, flags), flags); + field_ptr!(desc, Descriptor, flags).write(&flags).unwrap(); } self.num_used += (inputs.len() + outputs.len()) as u16; let avail_slot = self.avail_idx & (self.queue_size - 1); - self.avail.write_at( - (offset_of!(AvailRing, ring) as usize + avail_slot as usize * 2) as *const u16, - head, - ); - + { + let mut ring_ptr = field_ptr!(&self.avail, AvailRing, ring); + ring_ptr.byte_add(offset_of!(AvailRing, ring) as usize + avail_slot as usize * 2); + ring_ptr.cast::().write(&self.avail_idx).unwrap(); + } // write barrier fence(Ordering::SeqCst); // increase head of avail ring self.avail_idx = self.avail_idx.wrapping_add(1); - self.avail - .write_at(offset_of!(AvailRing, idx), self.avail_idx); + field_ptr!(&self.avail, AvailRing, idx) + .write(&self.avail_idx) + .unwrap(); fence(Ordering::SeqCst); Ok(head) @@ -213,7 +228,7 @@ impl VirtQueue { /// Whether there is a used element that can pop. pub fn can_pop(&self) -> bool { - self.last_used_idx != self.used.read_at(offset_of!(UsedRing, idx)) + self.last_used_idx != field_ptr!(&self.used, UsedRing, idx).read().unwrap() } /// The number of free descriptors. @@ -233,15 +248,19 @@ impl VirtQueue { head - 1 }; let temp_desc = &mut self.descs[last_free_head as usize]; - temp_desc.write_at(offset_of!(Descriptor, next), head); + field_ptr!(temp_desc, Descriptor, next) + .write(&head) + .unwrap(); loop { let desc = &mut self.descs[head as usize]; - let flags: DescFlags = desc.read_at(offset_of!(Descriptor, flags)); + let flags: DescFlags = field_ptr!(desc, Descriptor, flags).read().unwrap(); self.num_used -= 1; if flags.contains(DescFlags::NEXT) { - head = desc.read_at(offset_of!(Descriptor, next)); + head = field_ptr!(desc, Descriptor, next).read().unwrap(); } else { - desc.write_at(offset_of!(Descriptor, next), origin_free_head); + field_ptr!(desc, Descriptor, next) + .write(&origin_free_head) + .unwrap(); return; } } @@ -258,17 +277,18 @@ impl VirtQueue { fence(Ordering::SeqCst); let last_used_slot = self.last_used_idx & (self.queue_size - 1); - let index = self.used.read_at( - (offset_of!(UsedRing, ring) as usize + last_used_slot as usize * 8) as *const u32, - ) as u16; - let len = self.used.read_at( - (offset_of!(UsedRing, ring) as usize + last_used_slot as usize * 8 + 4) as *const u32, - ); + let element_ptr = { + let mut ptr = self.used.borrow_vm(); + ptr.byte_add(offset_of!(UsedRing, ring) as usize + last_used_slot as usize * 8); + ptr.cast::() + }; + let index = field_ptr!(&element_ptr, UsedElem, id).read().unwrap(); + let len = field_ptr!(&element_ptr, UsedElem, len).read().unwrap(); - self.recycle_descriptors(index); + self.recycle_descriptors(index as u16); self.last_used_idx = self.last_used_idx.wrapping_add(1); - Ok((index, len)) + Ok((index as u16, len)) } /// If the given token is next on the device used queue, pops it and returns the total buffer @@ -283,18 +303,19 @@ impl VirtQueue { fence(Ordering::SeqCst); let last_used_slot = self.last_used_idx & (self.queue_size - 1); - let index = self.used.read_at( - (offset_of!(UsedRing, ring) as usize + last_used_slot as usize * 8) as *const u32, - ) as u16; - let len = self.used.read_at( - (offset_of!(UsedRing, ring) as usize + last_used_slot as usize * 8 + 4) as *const u32, - ); + let element_ptr = { + let mut ptr = self.used.borrow_vm(); + ptr.byte_add(offset_of!(UsedRing, ring) as usize + last_used_slot as usize * 8); + ptr.cast::() + }; + let index = field_ptr!(&element_ptr, UsedElem, id).read().unwrap(); + let len = field_ptr!(&element_ptr, UsedElem, len).read().unwrap(); - if index != token { + if index as u16 != token { return Err(QueueError::WrongToken); } - self.recycle_descriptors(index); + self.recycle_descriptors(index as u16); self.last_used_idx = self.last_used_idx.wrapping_add(1); Ok(len) @@ -309,14 +330,13 @@ impl VirtQueue { pub fn should_notify(&self) -> bool { // read barrier fence(Ordering::SeqCst); - let flags = self.used.read_at(offset_of!(UsedRing, flags)); + let flags = field_ptr!(&self.used, UsedRing, flags).read().unwrap(); flags & 0x0001u16 == 0u16 } /// notify that there are available rings pub fn notify(&mut self) { - self.notify - .write_at(0 as usize as *const u32, self.queue_idx); + self.notify.write(&self.queue_idx).unwrap(); } } @@ -329,19 +349,16 @@ struct Descriptor { next: u16, } -impl Descriptor { - fn set_buf(&mut self, buf: &[u8]) { - self.addr = jinux_frame::vm::vaddr_to_paddr(buf.as_ptr() as usize).unwrap() as u64; - - self.len = buf.len() as u32; - } -} - -fn set_buf(inframe_ptr: &InFramePtr, buf: &[u8]) { +#[inline] +fn set_buf(ptr: &SafePtr>, buf: &[u8]) { let va = buf.as_ptr() as usize; let pa = jinux_frame::vm::vaddr_to_paddr(va).unwrap(); - inframe_ptr.write_at(offset_of!(Descriptor, addr), pa as u64); - inframe_ptr.write_at(offset_of!(Descriptor, len), buf.len() as u32); + field_ptr!(ptr, Descriptor, addr) + .write(&(pa as u64)) + .unwrap(); + field_ptr!(ptr, Descriptor, len) + .write(&(buf.len() as u32)) + .unwrap(); } bitflags! { /// Descriptor flags diff --git a/services/libs/jinux-util/src/frame_ptr.rs b/services/libs/jinux-util/src/frame_ptr.rs index 648dd0db..11be911e 100644 --- a/services/libs/jinux-util/src/frame_ptr.rs +++ b/services/libs/jinux-util/src/frame_ptr.rs @@ -6,7 +6,7 @@ use core::marker::PhantomData; use alloc::sync::Arc; use jinux_frame::{ io_mem::IoMem, - vm::{Paddr, VmFrame, VmIo}, + vm::{HasPaddr, Paddr, VmFrame, VmIo}, Result, }; use pod::Pod; diff --git a/services/libs/jinux-util/src/safe_ptr.rs b/services/libs/jinux-util/src/safe_ptr.rs index d77e50a7..ef7ae6a9 100644 --- a/services/libs/jinux-util/src/safe_ptr.rs +++ b/services/libs/jinux-util/src/safe_ptr.rs @@ -1,9 +1,12 @@ +use core::fmt::Debug; use core::marker::PhantomData; -use jinux_frame::vm::VmIo; +use jinux_frame::vm::Paddr; +use jinux_frame::vm::{HasPaddr, VmIo}; use jinux_frame::Result; use jinux_rights::{Dup, Exec, Full, Read, Signal, TRightSet, TRights, Write}; use jinux_rights_proc::require; -use pod::Pod; +pub use pod::Pod; +pub use typeflags_util::SetContain; /// Safe pointers. /// @@ -48,10 +51,10 @@ use pod::Pod; /// ``` /// /// The generic parameter `M` of `SafePtr<_, M, _>` must implement the `VmIo` -/// trait. The most important `VmIo` types are `Vmar`, `Vmo`, `Mmio`, and +/// trait. The most important `VmIo` types are `Vmar`, `Vmo`, `IoMem`, and /// `VmFrame`. The blanket implementations of `VmIo` also include pointer-like /// types that refer to a `VmIo` type. Some examples are `&Vmo`, `Box`, -/// and `Arc`. +/// and `Arc`. /// /// The safe pointer itself does not and cannot guarantee that its address is valid. /// This is because different VM objects may interpret addresses differently @@ -144,7 +147,7 @@ use pod::Pod; /// A safe pointer may have a combination of three access rights: /// Read, Write, and Dup. pub struct SafePtr { - addr: usize, + offset: usize, vm_obj: M, rights: R, phantom: PhantomData, @@ -157,17 +160,23 @@ impl SafePtr { /// /// The default access rights of a new instance are `Read`, `Write`, and /// `Dup`. - pub fn new(vm_obj: M, addr: usize) -> Self { + pub fn new(vm_obj: M, offset: usize) -> Self { Self { vm_obj, - addr, + offset, rights: TRightSet(::new()), phantom: PhantomData, } } } -impl SafePtr { +impl SafePtr { + pub fn paddr(&self) -> Paddr { + self.vm_obj.paddr() + self.offset + } +} + +impl SafePtr> { // =============== Read and write methods ============== /// Read the value from the pointer. @@ -177,7 +186,7 @@ impl SafePtr { /// This method requires the Read right. #[require(R > Read)] pub fn read(&self) -> Result { - self.vm_obj.read_val(self.addr) + self.vm_obj.read_val(self.offset) } /// Read a slice of values from the pointer. @@ -197,7 +206,7 @@ impl SafePtr { /// This method requires the Write right. #[require(R > Write)] pub fn write(&self, val: &T) -> Result<()> { - self.vm_obj.write_val(self.addr, val) + self.vm_obj.write_val(self.offset, val) } /// Overwrite a slice of values at the pointer. @@ -212,45 +221,37 @@ impl SafePtr { // =============== Address-related methods ============== - pub const fn addr(&self) -> usize { - self.addr - } - - pub fn set_addr(&mut self, addr: usize) { - self.addr = addr; - } - pub const fn is_aligned(&self) -> bool { - self.addr % core::mem::align_of::() == 0 + self.offset % core::mem::align_of::() == 0 } /// Increase the address in units of bytes occupied by the generic T. pub fn add(&mut self, count: usize) { let offset = count * core::mem::size_of::(); - self.addr += offset; + self.offset += offset; } /// Increase or decrease the address in units of bytes occupied by the generic T. pub fn offset(&mut self, count: isize) { let offset = count * core::mem::size_of::() as isize; if count >= 0 { - self.addr += offset as usize; + self.offset += offset as usize; } else { - self.addr -= (-offset) as usize; + self.offset -= (-offset) as usize; } } /// Increase the address in units of bytes. pub fn byte_add(&mut self, bytes: usize) { - self.addr += bytes; + self.offset += bytes; } /// Increase or decrease the address in units of bytes. pub fn byte_offset(&mut self, bytes: isize) { if bytes >= 0 { - self.addr += bytes as usize; + self.offset += bytes as usize; } else { - self.addr -= (-bytes) as usize; + self.offset -= (-bytes) as usize; } } @@ -265,15 +266,15 @@ impl SafePtr { } /// Construct a new SafePtr which will point to the same address - pub const fn borrow_vm(&self) -> SafePtr { + pub fn borrow_vm(&self) -> SafePtr> { let SafePtr { - addr, + offset: addr, vm_obj, rights, .. } = self; SafePtr { - addr: *addr, + offset: *addr, vm_obj, rights: *rights, phantom: PhantomData, @@ -283,15 +284,15 @@ impl SafePtr { // =============== Type conversion methods ============== /// Cast the accessed structure into a new one, which is usually used when accessing a field in a structure. - pub fn cast(self) -> SafePtr { + pub fn cast(self) -> SafePtr> { let SafePtr { - addr, + offset: addr, vm_obj, rights, .. } = self; SafePtr { - addr, + offset: addr, vm_obj, rights, phantom: PhantomData, @@ -304,22 +305,26 @@ impl SafePtr { /// /// This method requires the target rights to be a subset of the current rights. #[require(R > R1)] - pub fn restrict(self) -> SafePtr { - let SafePtr { addr, vm_obj, .. } = self; - SafePtr { - addr, + pub fn restrict(self) -> SafePtr> { + let SafePtr { + offset: addr, vm_obj, - rights: R1::new(), + .. + } = self; + SafePtr { + offset: addr, + vm_obj, + rights: TRightSet(R1::new()), phantom: PhantomData, } } } #[require(R > Dup)] -impl Clone for SafePtr { +impl Clone for SafePtr> { fn clone(&self) -> Self { Self { - addr: self.addr, + offset: self.offset, vm_obj: self.vm_obj.clone(), rights: self.rights, phantom: PhantomData, @@ -328,10 +333,10 @@ impl Clone for SafePtr { } #[require(R > Dup)] -impl crate::dup::Dup for SafePtr { +impl crate::dup::Dup for SafePtr> { fn dup(&self) -> Result { let duplicated = Self { - addr: self.addr, + offset: self.offset, vm_obj: self.vm_obj.dup()?, rights: self.rights, phantom: PhantomData, @@ -340,33 +345,44 @@ impl crate::dup::Dup for SafePtr { } } +impl Debug for SafePtr { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + f.debug_struct("SafePtr") + .field("offset", &self.offset) + .field("vm_obj", &self.vm_obj) + .finish() + } +} + /// Create a safe pointer for the field of a struct. #[macro_export] macro_rules! field_ptr { ($ptr:expr, $type:ty, $($field:tt)+) => {{ use jinux_frame::offset_of; use jinux_frame::vm::VmIo; - // import more... + use jinux_rights::TRights; + use jinux_rights::TRightSet; + use jinux_rights::Dup; + use jinux_util::safe_ptr::SetContain; + use jinux_util::safe_ptr::Pod; #[inline] fn new_field_ptr( - container_ptr: &SafePtr, + container_ptr: &SafePtr>, field_offset: *const U - ) -> SafePtr + ) -> SafePtr> where T: Pod, M: VmIo, R: TRights, U: Pod, { - container_ptr - .borrow_vm() - .byte_add(offset as usize) - .cast() + let mut ptr = container_ptr.borrow_vm(); + ptr.byte_add(field_offset as usize); + ptr.cast() } - let ptr = $ptr; - let field_offset = offset_of!(ty, $($field)*); - new_field_ptr(ptr, field_offset) + let field_offset = offset_of!($type, $($field)*); + new_field_ptr($ptr,field_offset) }} }