mirror of
https://github.com/asterinas/asterinas.git
synced 2025-06-23 17:33:23 +00:00
Replace InFramePtr with SafePtr
This commit is contained in:
committed by
Tate, Hongliang Tian
parent
ab4b1b47dc
commit
c38e4f0800
@ -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
|
||||
|
Reference in New Issue
Block a user