Change physical address accees to MMIO

This commit is contained in:
Yuke Peng 2023-05-05 03:07:51 -07:00 committed by Tate, Hongliang Tian
parent 5656805520
commit 42ecbe1b04
9 changed files with 184 additions and 224 deletions

View File

@ -35,9 +35,6 @@ impl VmFrameVec {
let page_size = options.page_size;
let mut frame_list = Vec::new();
if options.is_contiguous {
if options.paddr.is_some() {
panic!("not support contiguous paddr");
}
let frames = frame_allocator::alloc_continuous(options.page_size);
if frames.is_none() {
return Err(Error::NoMemory);
@ -45,15 +42,7 @@ impl VmFrameVec {
return Ok(Self(frames.unwrap()));
}
for i in 0..page_size {
let vm_frame = if let Some(paddr) = options.paddr {
frame_allocator::alloc_with_paddr(paddr + i * PAGE_SIZE)
} else {
frame_allocator::alloc()
};
if vm_frame.is_none() {
return Err(Error::NoMemory);
}
frame_list.push(vm_frame.unwrap());
frame_list.push(frame_allocator::alloc().unwrap());
}
Ok(Self(frame_list))
}
@ -211,7 +200,6 @@ impl<'a> Iterator for VmFrameVecIter<'a> {
/// See `VmFrameVec::alloc`.
pub struct VmAllocOptions {
page_size: usize,
paddr: Option<Paddr>,
is_contiguous: bool,
}
@ -220,22 +208,10 @@ impl VmAllocOptions {
pub fn new(len: usize) -> Self {
Self {
page_size: len,
paddr: None,
is_contiguous: false,
}
}
/// Sets the physical address of the first frame.
///
/// If the physical address is given, then the allocated frames will be
/// contiguous.
///
/// The default value is `None`.
pub fn paddr(&mut self, paddr: Option<Paddr>) -> &mut Self {
self.paddr = paddr;
self
}
/// Sets whether the allocated frames should be contiguous.
///
/// If the physical address is set, then the frames must be contiguous.
@ -366,14 +342,13 @@ impl VmIo for VmFrame {
/// Read a value of a specified type at a specified offset.
fn read_val<T: Pod>(&self, offset: usize) -> Result<T> {
let paddr = self.start_paddr() + offset;
let val = unsafe { &mut *(super::paddr_to_vaddr(paddr) as *mut T) };
Ok(*val)
Ok(unsafe { core::ptr::read(super::paddr_to_vaddr(paddr) as *const T) })
}
/// Write a value of a specified type at a specified offset.
fn write_val<T: Pod>(&self, offset: usize, new_val: &T) -> Result<()> {
let paddr = self.start_paddr() + offset;
unsafe { (super::paddr_to_vaddr(paddr) as *mut T).write(*new_val) };
unsafe { core::ptr::write(super::paddr_to_vaddr(paddr) as *mut T, *new_val) };
Ok(())
}
}

View File

@ -41,43 +41,6 @@ pub fn alloc_continuous(frame_count: usize) -> Option<Vec<VmFrame>> {
})
}
pub fn alloc_with_paddr(paddr: Paddr) -> Option<VmFrame> {
if !is_paddr_valid(paddr..paddr + PAGE_SIZE) {
debug!("not a valid paddr:{:x}", paddr);
return None;
}
unsafe {
Some(VmFrame::new(
paddr.align_down(PAGE_SIZE),
VmFrameFlags::empty(),
))
}
}
/// Check if the physical address in range is valid
fn is_paddr_valid(range: Range<usize>) -> bool {
// special area in x86
#[cfg(target_arch = "x86_64")]
if range.start >= 0xFE00_0000 && range.end <= 0xFFFF_FFFF {
return true;
}
for i in super::MEMORY_REGIONS.get().unwrap().iter() {
match i.typ {
MemoryRegionsType::Usable => {}
MemoryRegionsType::Reserved => {}
MemoryRegionsType::Framebuffer => {}
_ => {
continue;
}
}
if range.start as u64 >= i.base && (range.end as u64) <= i.base + i.len {
return true;
}
}
false
}
pub(crate) fn alloc_zero() -> Option<VmFrame> {
let frame = alloc()?;
frame.zero();

View File

@ -12,11 +12,7 @@ use core::{
ops::{Index, IndexMut},
};
use font8x8::UnicodeFonts;
use jinux_frame::{
config::PAGE_SIZE,
vm::{VmAllocOptions, VmFrameVec, VmIo},
LimineFramebufferRequest,
};
use jinux_frame::{config::PAGE_SIZE, mmio::Mmio, vm::VmIo, LimineFramebufferRequest};
use spin::{Mutex, Once};
#[init_component]
@ -43,10 +39,10 @@ pub(crate) fn init() {
for i in response.framebuffers() {
let page_size = size / PAGE_SIZE;
let frame_vec = VmFrameVec::allocate(VmAllocOptions::new(page_size).paddr(
jinux_frame::vm::vaddr_to_paddr(i.address.as_ptr().unwrap().addr()),
))
.unwrap();
let start_paddr = i.address.as_ptr().unwrap().addr();
let mmio =
Mmio::new(start_paddr..(start_paddr + jinux_frame::config::PAGE_SIZE * page_size))
.unwrap();
let mut buffer: Vec<u8> = Vec::with_capacity(size);
for _ in 0..size {
@ -55,7 +51,7 @@ pub(crate) fn init() {
log::debug!("Found framebuffer:{:?}", *i);
writer = Some(Writer {
frame_vec,
mmio,
x_pos: 0,
y_pos: 0,
bytes_per_pixel: (i.bpp / 8) as usize,
@ -72,7 +68,7 @@ pub(crate) fn init() {
}
pub(crate) struct Writer {
frame_vec: VmFrameVec,
mmio: Mmio,
/// FIXME: remove buffer. The meaning of buffer is to facilitate the various operations of framebuffer
buffer: &'static mut [u8],
@ -99,14 +95,14 @@ impl Writer {
self.x_pos = 0;
self.y_pos = 0;
self.buffer.fill(0);
self.frame_vec.write_bytes(0, self.buffer).unwrap();
self.mmio.write_bytes(0, self.buffer).unwrap();
}
/// Everything moves up one letter in size
fn shift_lines_up(&mut self) {
let offset = self.bytes_per_pixel * 8;
self.buffer.copy_within(offset.., 0);
self.frame_vec.write_bytes(0, self.buffer).unwrap();
self.mmio.write_bytes(0, self.buffer).unwrap();
self.y_pos -= 8;
}
@ -159,7 +155,7 @@ impl Writer {
self.buffer
.index_mut(byte_offset..(byte_offset + bytes_per_pixel))
.copy_from_slice(&color[..bytes_per_pixel]);
self.frame_vec
self.mmio
.write_bytes(
byte_offset,
self.buffer

View File

@ -83,21 +83,22 @@ 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);
for i in 0..table_size {
let value: InFramePtr<MSIXTableEntry> =
InFramePtr::new(table_base_address as usize + 16 * i as usize)
.expect("can not get in frame ptr for msix");
let mut table_iter: InFramePtr<MSIXTableEntry> =
InFramePtr::new(table_base_address as usize)
.expect("can not get in frame ptr for msix");
for _ in 0..table_size {
// local APIC address: 0xFEE0_0000
value.write_at(offset_of!(MSIXTableEntry, msg_addr), 0xFEE0_0000 as u32);
value.write_at(offset_of!(MSIXTableEntry, msg_upper_addr), 0 as u32);
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);
// allocate irq number
let handle = jinux_frame::trap::allocate_irq().expect("not enough irq");
value.write_at(offset_of!(MSIXTableEntry, msg_data), handle.num() as u32);
value.write_at(offset_of!(MSIXTableEntry, vector_control), 0 as u32);
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);
cap.table.push(MSIXEntry {
table_entry: value,
table_entry: table_iter.clone(),
irq_handle: handle,
});
table_iter = table_iter.add(1);
}
cap
}

View File

@ -267,6 +267,10 @@ impl PCIVirtioDevice {
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;
// Reset device
common_cfg_frame_ptr.write_at(offset_of!(VitrioPciCommonCfg, device_status), 0 as u8);
let num_queues: u16 =
common_cfg_frame_ptr.read_at(offset_of!(VitrioPciCommonCfg, num_queues));
debug!("num_queues:{:x}", num_queues);

View File

@ -6,7 +6,7 @@ use bitflags::bitflags;
use core::sync::atomic::{fence, Ordering};
use jinux_frame::{
offset_of,
vm::{VmAllocOptions, VmFrame, VmFrameVec},
vm::{VmAllocOptions, VmFrameVec},
};
use jinux_util::frame_ptr::InFramePtr;
use log::debug;
@ -45,13 +45,11 @@ pub struct VirtQueue {
/// The number of used queues.
num_used: u16,
/// The head desc index of the free list.
pub free_head: u16,
free_head: u16,
/// the index of the next avail ring index
avail_idx: u16,
/// last service used index
last_used_idx: u16,
physical_frame_store: Vec<VmFrame>,
}
impl VirtQueue {
@ -69,9 +67,7 @@ impl VirtQueue {
cfg.read_at(offset_of!(VitrioPciCommonCfg, queue_select)),
idx as u16
);
// info!("actual queue_size:{}",cfg.read_at(offset_of!(VitrioPciCommonCfg, queue_size)));
if !size.is_power_of_two() || cfg.read_at(offset_of!(VitrioPciCommonCfg, queue_size)) < size
{
if !size.is_power_of_two() {
return Err(QueueError::InvalidArgs);
}
@ -85,63 +81,54 @@ impl VirtQueue {
msix_vector
);
let mut descs = Vec::new();
//allocate page
let mut frame_vec = Vec::new();
let vm_allocate_option = VmAllocOptions::new(1);
if cfg.read_at(offset_of!(VitrioPciCommonCfg, queue_desc)) == 0 as u64 {
let frame = VmFrameVec::allocate(&vm_allocate_option)
.expect("cannot allocate physical frame for virtqueue")
.remove(0);
cfg.write_at(
offset_of!(VitrioPciCommonCfg, queue_desc),
frame.start_paddr() as u64,
);
debug!("queue_desc vm frame:{:x?}", frame);
frame_vec.push(frame);
let desc_frame_ptr: InFramePtr<Descriptor> = InFramePtr::new_with_vm_frame(
VmFrameVec::allocate(&VmAllocOptions::new(1))
.unwrap()
.pop()
.unwrap(),
)
.unwrap();
let avail_frame_ptr: InFramePtr<AvailRing> = InFramePtr::new_with_vm_frame(
VmFrameVec::allocate(&VmAllocOptions::new(1))
.unwrap()
.pop()
.unwrap(),
)
.unwrap();
let used_frame_ptr: InFramePtr<UsedRing> = InFramePtr::new_with_vm_frame(
VmFrameVec::allocate(&VmAllocOptions::new(1))
.unwrap()
.pop()
.unwrap(),
)
.unwrap();
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!(VitrioPciCommonCfg, queue_desc),
desc_frame_ptr.paddr() as u64,
);
cfg.write_at(
offset_of!(VitrioPciCommonCfg, queue_driver),
avail_frame_ptr.paddr() as u64,
);
cfg.write_at(
offset_of!(VitrioPciCommonCfg, queue_device),
used_frame_ptr.paddr() as u64,
);
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))
}
if cfg.read_at(offset_of!(VitrioPciCommonCfg, queue_driver)) == 0 as u64 {
let frame = VmFrameVec::allocate(&vm_allocate_option)
.expect("cannot allocate physical frame for virtqueue")
.remove(0);
cfg.write_at(
offset_of!(VitrioPciCommonCfg, queue_driver),
frame.start_paddr() as u64,
);
debug!("queue_driver vm frame:{:x?}", frame);
frame_vec.push(frame);
}
if cfg.read_at(offset_of!(VitrioPciCommonCfg, queue_device)) == 0 as u64 {
let frame = VmFrameVec::allocate(&vm_allocate_option)
.expect("cannot allocate physical frame for virtqueue")
.remove(0);
cfg.write_at(
offset_of!(VitrioPciCommonCfg, queue_device),
frame.start_paddr() as u64,
);
debug!("queue_device vm frame:{:x?}", frame);
frame_vec.push(frame);
}
for i in 0..size {
descs.push(
InFramePtr::new(
cfg.read_at(offset_of!(VitrioPciCommonCfg, queue_desc)) as usize
+ i as usize * 16,
)
.expect("can not get Inframeptr for virtio queue Descriptor"),
)
}
let avail =
InFramePtr::new(cfg.read_at(offset_of!(VitrioPciCommonCfg, queue_driver)) as usize)
.expect("can not get Inframeptr for virtio queue available ring");
let used =
InFramePtr::new(cfg.read_at(offset_of!(VitrioPciCommonCfg, queue_device)) as usize)
.expect("can not get Inframeptr for virtio queue used ring");
let notify = InFramePtr::new(notify_base_address + notify_off_multiplier as usize * idx)
.expect("can not get Inframeptr for virtio queue notify");
// Link descriptors together.
@ -149,12 +136,12 @@ impl VirtQueue {
let temp = descs.get(i as usize).unwrap();
temp.write_at(offset_of!(Descriptor, next), i + 1);
}
avail.write_at(offset_of!(AvailRing, flags), 0 as u16);
avail_frame_ptr.write_at(offset_of!(AvailRing, flags), 0 as u16);
cfg.write_at(offset_of!(VitrioPciCommonCfg, queue_enable), 1 as u16);
Ok(VirtQueue {
descs,
avail,
used,
avail: avail_frame_ptr,
used: used_frame_ptr,
notify,
queue_size: size,
queue_idx: idx as u32,
@ -162,7 +149,6 @@ impl VirtQueue {
free_head: 0,
avail_idx: 0,
last_used_idx: 0,
physical_frame_store: frame_vec,
})
}
@ -346,8 +332,6 @@ impl Descriptor {
fn set_buf(inframe_ptr: &InFramePtr<Descriptor>, buf: &[u8]) {
let va = buf.as_ptr() as usize;
let pa = jinux_frame::vm::vaddr_to_paddr(va).unwrap();
debug!("set buf write virt address:{:x}", va);
debug!("set buf write phys address:{:x}", pa);
inframe_ptr.write_at(offset_of!(Descriptor, addr), pa as u64);
inframe_ptr.write_at(offset_of!(Descriptor, len), buf.len() as u32);
}

View File

@ -4,7 +4,7 @@ use core::ops::Range;
use crate::rights::Rights;
use align_ext::AlignExt;
use jinux_frame::vm::{Paddr, VmAllocOptions, VmFrameVec, VmIo};
use jinux_frame::vm::{VmAllocOptions, VmFrameVec, VmIo};
use crate::prelude::*;
@ -142,8 +142,6 @@ pub(super) struct Vmo_ {
inner: Mutex<VmoInner>,
/// Parent Vmo
parent: Weak<Vmo_>,
/// paddr
paddr: Option<Paddr>,
/// vmo type
vmo_type: VmoType,
}
@ -419,10 +417,6 @@ impl Vmo_ {
Ok(())
}
pub fn paddr(&self) -> Option<Paddr> {
self.paddr
}
pub fn flags(&self) -> VmoFlags {
self.flags.clone()
}
@ -434,12 +428,6 @@ impl<R> Vmo<R> {
self.0.size()
}
/// Returns the starting physical address of a VMO, if it is contiguous.
/// Otherwise, returns none.
pub fn paddr(&self) -> Option<Paddr> {
self.0.paddr()
}
/// Returns the flags of a VMO.
pub fn flags(&self) -> VmoFlags {
self.0.flags()

View File

@ -4,7 +4,7 @@ use core::marker::PhantomData;
use core::ops::Range;
use align_ext::AlignExt;
use jinux_frame::vm::{Paddr, VmAllocOptions, VmFrameVec};
use jinux_frame::vm::{VmAllocOptions, VmFrameVec};
use jinux_rights_proc::require;
use typeflags_util::{SetExtend, SetExtendOp};
@ -54,7 +54,6 @@ use super::{Pager, Vmo, VmoFlags};
/// ```
pub struct VmoOptions<R = Rights> {
size: usize,
paddr: Option<Paddr>,
flags: VmoFlags,
rights: Option<R>,
pager: Option<Arc<dyn Pager>>,
@ -68,25 +67,12 @@ impl<R> VmoOptions<R> {
pub fn new(size: usize) -> Self {
Self {
size,
paddr: None,
flags: VmoFlags::empty(),
rights: None,
pager: None,
}
}
/// Sets the starting physical address of the VMO.
///
/// By default, this option is not set.
///
/// If this option is set, then the underlying pages of VMO must be contiguous.
/// So `VmoFlags::IS_CONTIGUOUS` will be set automatically.
pub fn paddr(mut self, paddr: Paddr) -> Self {
self.paddr = Some(paddr);
self.flags |= VmoFlags::CONTIGUOUS;
self
}
/// Sets the VMO flags.
///
/// The default value is `VmoFlags::empty()`.
@ -112,13 +98,9 @@ impl VmoOptions<Rights> {
/// The VMO is initially assigned full access rights.
pub fn alloc(self) -> Result<Vmo<Rights>> {
let VmoOptions {
size,
paddr,
flags,
pager,
..
size, flags, pager, ..
} = self;
let vmo_ = alloc_vmo_(size, paddr, flags, pager)?;
let vmo_ = alloc_vmo_(size, flags, pager)?;
Ok(Vmo(Arc::new(vmo_), Rights::all()))
}
}
@ -133,24 +115,18 @@ impl<R: TRights> VmoOptions<R> {
pub fn alloc(self) -> Result<Vmo<R>> {
let VmoOptions {
size,
paddr,
flags,
rights,
pager,
} = self;
let vmo_ = alloc_vmo_(size, paddr, flags, pager)?;
let vmo_ = alloc_vmo_(size, flags, pager)?;
Ok(Vmo(Arc::new(vmo_), R::new()))
}
}
fn alloc_vmo_(
size: usize,
paddr: Option<Paddr>,
flags: VmoFlags,
pager: Option<Arc<dyn Pager>>,
) -> Result<Vmo_> {
fn alloc_vmo_(size: usize, flags: VmoFlags, pager: Option<Arc<dyn Pager>>) -> Result<Vmo_> {
let size = size.align_up(PAGE_SIZE);
let committed_pages = committed_pages_if_continuous(flags, size, paddr)?;
let committed_pages = committed_pages_if_continuous(flags, size)?;
let vmo_inner = VmoInner {
pager,
size,
@ -161,7 +137,6 @@ fn alloc_vmo_(
flags,
inner: Mutex::new(vmo_inner),
parent: Weak::new(),
paddr,
vmo_type: VmoType::NotChild,
})
}
@ -169,14 +144,12 @@ fn alloc_vmo_(
fn committed_pages_if_continuous(
flags: VmoFlags,
size: usize,
paddr: Option<Paddr>,
) -> Result<BTreeMap<usize, VmFrameVec>> {
if flags.contains(VmoFlags::CONTIGUOUS) {
// if the vmo is continuous, we need to allocate frames for the vmo
let frames_num = size / PAGE_SIZE;
let mut vm_alloc_option = VmAllocOptions::new(frames_num);
vm_alloc_option.is_contiguous(true);
vm_alloc_option.paddr(paddr);
let frames = VmFrameVec::allocate(&vm_alloc_option)?;
let mut committed_pages = BTreeMap::new();
for (idx, frame) in frames.into_iter().enumerate() {
@ -500,9 +473,6 @@ fn alloc_child_vmo_(
committed_pages: BTreeMap::new(),
inherited_pages,
};
let child_paddr = parent_vmo_
.paddr()
.map(|parent_paddr| parent_paddr + child_vmo_start);
let vmo_type = match child_type {
ChildType::Cow => VmoType::CopyOnWriteChild,
ChildType::Slice => VmoType::SliceChild,
@ -511,7 +481,6 @@ fn alloc_child_vmo_(
flags: child_flags,
inner: Mutex::new(vmo_inner),
parent: Arc::downgrade(&parent_vmo_),
paddr: child_paddr,
vmo_type,
})
}

View File

@ -1,47 +1,74 @@
extern crate alloc;
use core::marker::PhantomData;
use alloc::sync::Arc;
use jinux_frame::{
config::PAGE_SIZE,
vm::{Paddr, VmAllocOptions, VmFrame, VmFrameVec, VmIo},
mmio::Mmio,
vm::{Paddr, VmFrame, VmIo},
Result,
};
use pod::Pod;
#[derive(Debug, Clone)]
enum InFramePtrAccessMethod {
Mmio(Mmio),
VmFrame(Arc<VmFrame>),
}
/// An in-frame pointer to a POD value, enabling safe access
/// to a POD value given its physical memory address.
#[derive(Debug)]
pub struct InFramePtr<T: 'static> {
frame: VmFrame,
access_method: InFramePtrAccessMethod,
offset: usize,
marker: PhantomData<&'static mut T>,
}
impl<T: Pod> InFramePtr<T> {
/// This function only allow the physical address in the MMIO region.
///
/// Panic if the physical address is not in MMIO region.
pub fn new(paddr: Paddr) -> Result<Self> {
let frame = {
let page_paddr = paddr & !(PAGE_SIZE - 1);
let mut options = VmAllocOptions::new(1);
options.paddr(Some(page_paddr));
VmFrameVec::allocate(&options)?.remove(0)
};
let offset = paddr - frame.start_paddr();
let limit = core::mem::size_of::<T>();
Ok(Self {
frame,
offset,
access_method: InFramePtrAccessMethod::Mmio(
jinux_frame::mmio::Mmio::new(paddr..paddr + limit).unwrap(),
),
offset: 0,
marker: PhantomData,
})
}
/// Creating a pointer to the inside of VmFrame.
pub fn new_with_vm_frame(vm_frame_vec: VmFrame) -> Result<Self> {
Ok(Self {
access_method: InFramePtrAccessMethod::VmFrame(Arc::new(vm_frame_vec)),
offset: 0,
marker: PhantomData,
})
}
pub fn read_at<F: Pod>(&self, offset: *const F) -> F {
self.frame
.read_val::<F>(self.offset + offset as usize)
.expect("read data from frame failed")
match &self.access_method {
InFramePtrAccessMethod::Mmio(mmio) => mmio
.read_val::<F>(self.offset + offset as usize)
.expect("write data from frame failed"),
InFramePtrAccessMethod::VmFrame(vm_frame) => vm_frame
.read_val::<F>(self.offset + offset as usize)
.expect("write data from frame failed"),
}
}
pub fn write_at<F: Pod>(&self, offset: *const F, new_val: F) {
self.frame
.write_val::<F>(self.offset + offset as usize, &new_val)
.expect("write data from frame failed");
match &self.access_method {
InFramePtrAccessMethod::Mmio(mmio) => mmio
.write_val::<F>(self.offset + offset as usize, &new_val)
.expect("write data from frame failed"),
InFramePtrAccessMethod::VmFrame(vm_frame) => vm_frame
.write_val::<F>(self.offset + offset as usize, &new_val)
.expect("write data from frame failed"),
}
}
pub fn offset(&self) -> usize {
@ -49,6 +76,59 @@ impl<T: Pod> InFramePtr<T> {
}
pub fn paddr(&self) -> usize {
self.offset + self.frame.start_paddr()
match &self.access_method {
InFramePtrAccessMethod::Mmio(mmio) => self.offset + mmio.paddr(),
InFramePtrAccessMethod::VmFrame(vm_frame) => self.offset + vm_frame.start_paddr(),
}
}
/// Clone self and then change the offset to the next `count` one.
///
/// User can use this function to easily visit POD array. For example:
///
/// ```rust
/// use pod::Pod
///
/// #[derive(Pod)]
/// struct Foo{
/// value1: usize,
/// value2: usize,
/// }
///
/// fn visit(){
/// // visit array [Foo1, Foo2, Foo3]
/// let Foo1 : InFramePtr<Foo> = InFramePtr::alloc().unwrap();
/// let Foo2 = Foo1.add(1);
/// let Foo3 = Foo2.add(1);
/// }
///
/// ```
///
pub fn add(&self, count: usize) -> Self {
let mut next: InFramePtr<T> = self.clone();
next.access_method = match next.access_method {
InFramePtrAccessMethod::Mmio(mmio) => InFramePtrAccessMethod::Mmio(
jinux_frame::mmio::Mmio::new(
mmio.paddr() + count * core::mem::size_of::<T>()
..mmio.paddr() + (count + 1) * core::mem::size_of::<T>(),
)
.unwrap(),
),
InFramePtrAccessMethod::VmFrame(_) => {
next.offset += core::mem::size_of::<T>() * count;
next.access_method
}
};
next
}
}
impl<T: Pod> Clone for InFramePtr<T> {
fn clone(&self) -> Self {
Self {
access_method: self.access_method.clone(),
offset: self.offset,
marker: self.marker,
}
}
}