Replace InFramePtr with SafePtr
This commit is contained in:
parent
ab4b1b47dc
commit
c38e4f0800
|
@ -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]]
|
||||
|
|
|
@ -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<Paddr>) -> Option<IoMem> {
|
||||
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 {
|
||||
|
|
|
@ -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.
|
||||
///
|
||||
|
|
|
@ -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<Paddr> {
|
||||
|
@ -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<Vec<MemoryRegion>> = Once::new();
|
||||
|
||||
|
|
|
@ -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<BLKDevice>,
|
||||
pub common_cfg: InFramePtr<VirtioPciCommonCfg>,
|
||||
msix: MSIX,
|
||||
pub common_cfg: SafePtr<VirtioPciCommonCfg, IoMem>,
|
||||
_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,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -83,6 +83,7 @@ impl INPUTComponent {
|
|||
}
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
#[derive(Debug)]
|
||||
enum InputDeviceHandleError {
|
||||
DeviceNotExists,
|
||||
|
|
|
@ -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<VirtioPciCommonCfg>,
|
||||
msix: Mutex<MSIX>,
|
||||
_common_cfg: SafePtr<VirtioPciCommonCfg, IoMem>,
|
||||
_msix: Mutex<MSIX>,
|
||||
name: String,
|
||||
callbacks: Mutex<Vec<Arc<dyn Fn(DecodeType) + Send + Sync + 'static>>>,
|
||||
}
|
||||
|
@ -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()),
|
||||
},
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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<VirtioPciCommonCfg>,
|
||||
_common_cfg: SafePtr<VirtioPciCommonCfg, IoMem>,
|
||||
_msix: SpinLock<MSIX>,
|
||||
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 {
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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<MSIXTableEntry>,
|
||||
pub table_entry: SafePtr<MSIXTableEntry, IoMem>,
|
||||
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<MSIXTableEntry> =
|
||||
InFramePtr::new(table_base_address as usize)
|
||||
.expect("can not get in frame ptr for msix");
|
||||
let mut table_iter: SafePtr<MSIXTableEntry, IoMem> = SafePtr::new(
|
||||
IoMem::new(
|
||||
table_base_address as usize
|
||||
..table_base_address as usize
|
||||
+ (size_of::<MSIXTableEntry>() * 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
|
||||
}
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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<VirtioBLKConfig>,
|
||||
config: SafePtr<VirtioBLKConfig, IoMem>,
|
||||
queue: VirtQueue,
|
||||
}
|
||||
|
||||
|
@ -27,13 +27,15 @@ impl BLKDevice {
|
|||
pub(crate) fn new(
|
||||
cap: &CapabilityVirtioData,
|
||||
bars: [Option<BAR>; 6],
|
||||
common_cfg: &InFramePtr<VirtioPciCommonCfg>,
|
||||
common_cfg: &SafePtr<VirtioPciCommonCfg, IoMem>,
|
||||
notify_base_address: usize,
|
||||
notify_off_multiplier: u32,
|
||||
mut msix_vector_left: Vec<u16>,
|
||||
) -> Result<Self, VirtioDeviceError> {
|
||||
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));
|
||||
}
|
||||
|
|
|
@ -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<BAR>; 6]) -> InFramePtr<Self> {
|
||||
pub(crate) fn new(cap: &CapabilityVirtioData, bars: [Option<BAR>; 6]) -> SafePtr<Self, IoMem> {
|
||||
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::<Self>()),
|
||||
)
|
||||
.unwrap(),
|
||||
0,
|
||||
),
|
||||
BAR::IO(_, _) => panic!("Virtio pci block cfg:bar is IO type"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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<VirtioInputConfig>,
|
||||
config: SafePtr<VirtioInputConfig, IoMem>,
|
||||
event_queue: Mutex<VirtQueue>,
|
||||
status_queue: VirtQueue,
|
||||
pub event_buf: Mutex<Box<[InputEvent; QUEUE_SIZE]>>,
|
||||
|
@ -55,7 +55,7 @@ impl InputDevice {
|
|||
pub fn new(
|
||||
cap: &CapabilityVirtioData,
|
||||
bars: [Option<BAR>; 6],
|
||||
common_cfg: &InFramePtr<VirtioPciCommonCfg>,
|
||||
common_cfg: &SafePtr<VirtioPciCommonCfg, IoMem>,
|
||||
notify_base_address: usize,
|
||||
notify_off_multiplier: u32,
|
||||
mut msix_vector_left: Vec<u16>,
|
||||
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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<BAR>; 6]) -> InFramePtr<Self> {
|
||||
pub(crate) fn new(cap: &CapabilityVirtioData, bars: [Option<BAR>; 6]) -> SafePtr<Self, IoMem> {
|
||||
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::<Self>()),
|
||||
)
|
||||
.unwrap(),
|
||||
0,
|
||||
),
|
||||
BAR::IO(_, _) => panic!("Virtio pci block cfg:bar is IO type"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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<VirtioPciCommonCfg>,
|
||||
pub common_cfg_frame_ptr: SafePtr<VirtioPciCommonCfg, IoMem>,
|
||||
pub device_cap_cfg: CapabilityVirtioData,
|
||||
}
|
||||
|
||||
|
|
|
@ -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<BAR>; 6]) -> InFramePtr<Self> {
|
||||
pub(crate) fn new(cap: &CapabilityVirtioData, bars: [Option<BAR>; 6]) -> SafePtr<Self, IoMem> {
|
||||
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::<Self>()),
|
||||
)
|
||||
.unwrap(),
|
||||
0,
|
||||
),
|
||||
BAR::IO(_, _) => panic!("Virtio pci net cfg:bar is IO type"),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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<BAR>; 6],
|
||||
common_cfg: &InFramePtr<VirtioPciCommonCfg>,
|
||||
common_cfg: &SafePtr<VirtioPciCommonCfg, IoMem>,
|
||||
notify_base_address: usize,
|
||||
notify_off_multiplier: u32,
|
||||
mut msix_vector_left: Vec<u16>,
|
||||
|
@ -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,
|
||||
|
|
|
@ -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<BAR>; 6]) -> InFramePtr<Self> {
|
||||
pub(crate) fn new(cap: &CapabilityVirtioData, bars: [Option<BAR>; 6]) -> SafePtr<Self, IoMem> {
|
||||
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::<Self>()),
|
||||
)
|
||||
.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<VirtioPciCommonCfg>,
|
||||
pub common_cfg: SafePtr<VirtioPciCommonCfg, IoMem>,
|
||||
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<u16> = (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() {
|
||||
|
|
|
@ -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<InFramePtr<Descriptor>>,
|
||||
descs: Vec<SafePtr<Descriptor, VmFrame>>,
|
||||
/// Available ring
|
||||
avail: InFramePtr<AvailRing>,
|
||||
avail: SafePtr<AvailRing, VmFrame>,
|
||||
/// Used ring
|
||||
used: InFramePtr<UsedRing>,
|
||||
used: SafePtr<UsedRing, VmFrame>,
|
||||
/// point to notify address
|
||||
notify: InFramePtr<u32>,
|
||||
notify: SafePtr<u32, IoMem>,
|
||||
|
||||
/// 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<VirtioPciCommonCfg>,
|
||||
cfg: &SafePtr<VirtioPciCommonCfg, IoMem>,
|
||||
idx: usize,
|
||||
size: u16,
|
||||
notify_base_address: usize,
|
||||
notify_off_multiplier: u32,
|
||||
msix_vector: u16,
|
||||
) -> Result<Self, QueueError> {
|
||||
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<Descriptor> = InFramePtr::new_with_vm_frame(
|
||||
let desc_frame_ptr: SafePtr<Descriptor, VmFrame> = SafePtr::new(
|
||||
VmFrameVec::allocate(&VmAllocOptions::new(1).uninit(false).can_dma(true))
|
||||
.unwrap()
|
||||
.pop()
|
||||
.unwrap(),
|
||||
)
|
||||
.unwrap();
|
||||
let avail_frame_ptr: InFramePtr<AvailRing> = InFramePtr::new_with_vm_frame(
|
||||
0,
|
||||
);
|
||||
let avail_frame_ptr: SafePtr<AvailRing, VmFrame> = SafePtr::new(
|
||||
VmFrameVec::allocate(&VmAllocOptions::new(1).uninit(false).can_dma(true))
|
||||
.unwrap()
|
||||
.pop()
|
||||
.unwrap(),
|
||||
)
|
||||
.unwrap();
|
||||
let used_frame_ptr: InFramePtr<UsedRing> = InFramePtr::new_with_vm_frame(
|
||||
0,
|
||||
);
|
||||
let used_frame_ptr: SafePtr<UsedRing, VmFrame> = 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::<u32>()).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::<TRights![Write, Dup]>(), 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::<TRights![Write, Dup]>(), 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::<u16>().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::<UsedElem>()
|
||||
};
|
||||
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::<UsedElem>()
|
||||
};
|
||||
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<Descriptor>, buf: &[u8]) {
|
||||
#[inline]
|
||||
fn set_buf(ptr: &SafePtr<Descriptor, &VmFrame, TRightSet<TRights![Dup, Write]>>, 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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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<Vmar>`,
|
||||
/// and `Arc<Mmio>`.
|
||||
/// and `Arc<IoMem>`.
|
||||
///
|
||||
/// 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<T, M, R = Full> {
|
||||
addr: usize,
|
||||
offset: usize,
|
||||
vm_obj: M,
|
||||
rights: R,
|
||||
phantom: PhantomData<T>,
|
||||
|
@ -157,17 +160,23 @@ impl<T: Pod, M: VmIo> SafePtr<T, M> {
|
|||
///
|
||||
/// 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(<TRights![Dup, Read, Write, Exec, Signal]>::new()),
|
||||
phantom: PhantomData,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Pod, M: VmIo, R: TRights> SafePtr<T, M, R> {
|
||||
impl<T: Pod, M: VmIo + HasPaddr> SafePtr<T, M> {
|
||||
pub fn paddr(&self) -> Paddr {
|
||||
self.vm_obj.paddr() + self.offset
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Pod, M: VmIo, R: TRights> SafePtr<T, M, TRightSet<R>> {
|
||||
// =============== Read and write methods ==============
|
||||
|
||||
/// Read the value from the pointer.
|
||||
|
@ -177,7 +186,7 @@ impl<T: Pod, M: VmIo, R: TRights> SafePtr<T, M, R> {
|
|||
/// This method requires the Read right.
|
||||
#[require(R > Read)]
|
||||
pub fn read(&self) -> Result<T> {
|
||||
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<T: Pod, M: VmIo, R: TRights> SafePtr<T, M, R> {
|
|||
/// 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<T: Pod, M: VmIo, R: TRights> SafePtr<T, M, R> {
|
|||
|
||||
// =============== 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::<T>() == 0
|
||||
self.offset % core::mem::align_of::<T>() == 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::<T>();
|
||||
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::<T>() 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<T: Pod, M: VmIo, R: TRights> SafePtr<T, M, R> {
|
|||
}
|
||||
|
||||
/// Construct a new SafePtr which will point to the same address
|
||||
pub const fn borrow_vm(&self) -> SafePtr<T, &M, R> {
|
||||
pub fn borrow_vm(&self) -> SafePtr<T, &M, TRightSet<R>> {
|
||||
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<T: Pod, M: VmIo, R: TRights> SafePtr<T, M, R> {
|
|||
// =============== 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<U: Pod>(self) -> SafePtr<U, M, R> {
|
||||
pub fn cast<U: Pod>(self) -> SafePtr<U, M, TRightSet<R>> {
|
||||
let SafePtr {
|
||||
addr,
|
||||
offset: addr,
|
||||
vm_obj,
|
||||
rights,
|
||||
..
|
||||
} = self;
|
||||
SafePtr {
|
||||
addr,
|
||||
offset: addr,
|
||||
vm_obj,
|
||||
rights,
|
||||
phantom: PhantomData,
|
||||
|
@ -304,22 +305,26 @@ impl<T: Pod, M: VmIo, R: TRights> SafePtr<T, M, R> {
|
|||
///
|
||||
/// This method requires the target rights to be a subset of the current rights.
|
||||
#[require(R > R1)]
|
||||
pub fn restrict<R1: TRights>(self) -> SafePtr<T, M, R1> {
|
||||
let SafePtr { addr, vm_obj, .. } = self;
|
||||
SafePtr {
|
||||
addr,
|
||||
pub fn restrict<R1: TRights>(self) -> SafePtr<T, M, TRightSet<R1>> {
|
||||
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<T, M: Clone, R: TRights> Clone for SafePtr<T, M, R> {
|
||||
impl<T, M: Clone, R: TRights> Clone for SafePtr<T, M, TRightSet<R>> {
|
||||
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<T, M: Clone, R: TRights> Clone for SafePtr<T, M, R> {
|
|||
}
|
||||
|
||||
#[require(R > Dup)]
|
||||
impl<T, M: crate::dup::Dup, R: TRights> crate::dup::Dup for SafePtr<T, M, R> {
|
||||
impl<T, M: crate::dup::Dup, R: TRights> crate::dup::Dup for SafePtr<T, M, TRightSet<R>> {
|
||||
fn dup(&self) -> Result<Self> {
|
||||
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<T, M: crate::dup::Dup, R: TRights> crate::dup::Dup for SafePtr<T, M, R> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<T, M: Debug, R> Debug for SafePtr<T, M, R> {
|
||||
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<T, M, R, U>(
|
||||
container_ptr: &SafePtr<T, M, R>,
|
||||
container_ptr: &SafePtr<T, M, TRightSet<R>>,
|
||||
field_offset: *const U
|
||||
) -> SafePtr<U, &M, R>
|
||||
) -> SafePtr<U, &M, TRightSet<R>>
|
||||
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)
|
||||
}}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue