mirror of
https://github.com/asterinas/asterinas.git
synced 2025-06-28 11:53:24 +00:00
Remove AnyFrame
This commit is contained in:
committed by
Tate, Hongliang Tian
parent
c9a37ccab1
commit
14308f81b6
@ -38,6 +38,7 @@ pub(crate) mod mapping {
|
||||
use core::{
|
||||
any::Any,
|
||||
cell::UnsafeCell,
|
||||
fmt::Debug,
|
||||
mem::{size_of, MaybeUninit},
|
||||
sync::atomic::{AtomicU32, Ordering},
|
||||
};
|
||||
@ -113,7 +114,7 @@ const_assert_eq!(size_of::<MetaSlot>(), META_SLOT_SIZE);
|
||||
/// The implemented structure must have a size less than or equal to
|
||||
/// [`PAGE_METADATA_MAX_SIZE`] and an alignment less than or equal to
|
||||
/// [`PAGE_METADATA_MAX_ALIGN`].
|
||||
pub unsafe trait FrameMeta: Any + Send + Sync + 'static {
|
||||
pub unsafe trait FrameMeta: Any + Send + Sync + Debug + 'static {
|
||||
/// Called when the last handle to the page is dropped.
|
||||
fn on_drop(&mut self, _paddr: Paddr) {}
|
||||
}
|
||||
|
@ -20,10 +20,9 @@ mod segment;
|
||||
pub mod untyped;
|
||||
|
||||
use core::{
|
||||
any::Any,
|
||||
marker::PhantomData,
|
||||
mem::ManuallyDrop,
|
||||
sync::atomic::{AtomicUsize, Ordering},
|
||||
sync::atomic::{AtomicU32, AtomicUsize, Ordering},
|
||||
};
|
||||
|
||||
use meta::{
|
||||
@ -39,14 +38,15 @@ static MAX_PADDR: AtomicUsize = AtomicUsize::new(0);
|
||||
|
||||
/// A page with a statically-known usage, whose metadata is represented by `M`.
|
||||
#[derive(Debug)]
|
||||
pub struct Frame<M: FrameMeta> {
|
||||
#[repr(transparent)]
|
||||
pub struct Frame<M: FrameMeta + ?Sized> {
|
||||
pub(super) ptr: *const MetaSlot,
|
||||
pub(super) _marker: PhantomData<M>,
|
||||
}
|
||||
|
||||
unsafe impl<M: FrameMeta> Send for Frame<M> {}
|
||||
unsafe impl<M: FrameMeta + ?Sized> Send for Frame<M> {}
|
||||
|
||||
unsafe impl<M: FrameMeta> Sync for Frame<M> {}
|
||||
unsafe impl<M: FrameMeta + ?Sized> Sync for Frame<M> {}
|
||||
|
||||
impl<M: FrameMeta> Frame<M> {
|
||||
/// Get a `Frame` handle with a specific usage from a raw, unused page.
|
||||
@ -102,6 +102,78 @@ impl<M: FrameMeta> Frame<M> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Get the metadata of this page.
|
||||
pub fn meta(&self) -> &M {
|
||||
// SAFETY: `self.ptr` points to the metadata storage which is valid to
|
||||
// be immutably borrowed as `M` because the type is correct, it lives
|
||||
// under the given lifetime, and no one will mutably borrow the page
|
||||
// metadata after initialization.
|
||||
unsafe { &*self.ptr.cast() }
|
||||
}
|
||||
}
|
||||
|
||||
impl<M: FrameMeta + ?Sized> Frame<M> {
|
||||
/// Get the physical address.
|
||||
pub fn paddr(&self) -> Paddr {
|
||||
mapping::meta_to_page::<PagingConsts>(self.ptr as Vaddr)
|
||||
}
|
||||
|
||||
/// Get the paging level of this page.
|
||||
///
|
||||
/// This is the level of the page table entry that maps the frame,
|
||||
/// which determines the size of the frame.
|
||||
///
|
||||
/// Currently, the level is always 1, which means the frame is a regular
|
||||
/// page frame.
|
||||
pub const fn level(&self) -> PagingLevel {
|
||||
1
|
||||
}
|
||||
|
||||
/// Size of this page in bytes.
|
||||
pub const fn size(&self) -> usize {
|
||||
PAGE_SIZE
|
||||
}
|
||||
|
||||
/// Get the dyncamically-typed metadata of this frame.
|
||||
///
|
||||
/// If the type is known at compile time, use [`Frame::meta`] instead.
|
||||
pub fn dyn_meta(&self) -> &dyn FrameMeta {
|
||||
let slot = self.slot();
|
||||
|
||||
// SAFETY: The page metadata is valid to be borrowed immutably, since it will never be
|
||||
// borrowed mutably after initialization.
|
||||
let vtable_ptr = unsafe { &*slot.vtable_ptr.get() };
|
||||
|
||||
// SAFETY: The page metadata is initialized and valid.
|
||||
let vtable_ptr = *unsafe { vtable_ptr.assume_init_ref() };
|
||||
|
||||
let meta_ptr: *const dyn FrameMeta = core::ptr::from_raw_parts(self.ptr, vtable_ptr);
|
||||
|
||||
// SAFETY: `self.ptr` points to the metadata storage which is valid to be immutably
|
||||
// borrowed under `vtable_ptr` because the vtable is correct, it lives under the given
|
||||
// lifetime, and no one will mutably borrow the page metadata after initialization.
|
||||
unsafe { &*meta_ptr }
|
||||
}
|
||||
|
||||
/// Get the reference count of the page.
|
||||
///
|
||||
/// It returns the number of all references to the page, including all the
|
||||
/// existing page handles ([`Frame`], [`Frame<dyn FrameMeta>`]), and all the mappings in the
|
||||
/// page table that points to the page.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// The function is safe to call, but using it requires extra care. The
|
||||
/// reference count can be changed by other threads at any time including
|
||||
/// potentially between calling this method and acting on the result.
|
||||
pub fn reference_count(&self) -> u32 {
|
||||
self.ref_count().load(Ordering::Relaxed)
|
||||
}
|
||||
|
||||
fn ref_count(&self) -> &AtomicU32 {
|
||||
unsafe { &(*self.ptr).ref_count }
|
||||
}
|
||||
|
||||
/// Forget the handle to the page.
|
||||
///
|
||||
/// This will result in the page being leaked without calling the custom dropper.
|
||||
@ -138,58 +210,14 @@ impl<M: FrameMeta> Frame<M> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Get the physical address.
|
||||
pub fn paddr(&self) -> Paddr {
|
||||
mapping::meta_to_page::<PagingConsts>(self.ptr as Vaddr)
|
||||
}
|
||||
|
||||
/// Get the paging level of this page.
|
||||
///
|
||||
/// This is the level of the page table entry that maps the frame,
|
||||
/// which determines the size of the frame.
|
||||
///
|
||||
/// Currently, the level is always 1, which means the frame is a regular
|
||||
/// page frame.
|
||||
pub const fn level(&self) -> PagingLevel {
|
||||
1
|
||||
}
|
||||
|
||||
/// Size of this page in bytes.
|
||||
pub const fn size(&self) -> usize {
|
||||
PAGE_SIZE
|
||||
}
|
||||
|
||||
/// Get the metadata of this page.
|
||||
pub fn meta(&self) -> &M {
|
||||
// SAFETY: `self.ptr` points to the metadata storage which is valid to be immutably
|
||||
// borrowed as `M` because the type is correct, it lives under the given lifetime, and no
|
||||
// one will mutably borrow the page metadata after initialization.
|
||||
unsafe { &*self.ptr.cast() }
|
||||
}
|
||||
|
||||
/// Get the reference count of the page.
|
||||
///
|
||||
/// It returns the number of all references to the page, including all the
|
||||
/// existing page handles ([`Frame`], [`AnyFrame`]), and all the mappings in the
|
||||
/// page table that points to the page.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// The function is safe to call, but using it requires extra care. The
|
||||
/// reference count can be changed by other threads at any time including
|
||||
/// potentially between calling this method and acting on the result.
|
||||
pub fn reference_count(&self) -> u32 {
|
||||
self.slot().ref_count.load(Ordering::Relaxed)
|
||||
}
|
||||
|
||||
fn slot(&self) -> &MetaSlot {
|
||||
// SAFETY: `ptr` points to a valid `MetaSlot` that will never be mutably borrowed, so taking an
|
||||
// immutable reference to it is always safe.
|
||||
// SAFETY: `ptr` points to a valid `MetaSlot` that will never be
|
||||
// mutably borrowed, so taking an immutable reference to it is safe.
|
||||
unsafe { &*self.ptr }
|
||||
}
|
||||
}
|
||||
|
||||
impl<M: FrameMeta> Clone for Frame<M> {
|
||||
impl<M: FrameMeta + ?Sized> Clone for Frame<M> {
|
||||
fn clone(&self) -> Self {
|
||||
// SAFETY: We have already held a reference to the page.
|
||||
unsafe { self.slot().inc_ref_count() };
|
||||
@ -201,7 +229,7 @@ impl<M: FrameMeta> Clone for Frame<M> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<M: FrameMeta> Drop for Frame<M> {
|
||||
impl<M: FrameMeta + ?Sized> Drop for Frame<M> {
|
||||
fn drop(&mut self) {
|
||||
let last_ref_cnt = self.slot().ref_count.fetch_sub(1, Ordering::Release);
|
||||
debug_assert!(last_ref_cnt != 0 && last_ref_cnt != REF_COUNT_UNUSED);
|
||||
@ -219,147 +247,44 @@ impl<M: FrameMeta> Drop for Frame<M> {
|
||||
}
|
||||
}
|
||||
|
||||
/// A page with a dynamically-known usage.
|
||||
///
|
||||
/// It can also be used when the user don't care about the usage of the page.
|
||||
#[derive(Debug)]
|
||||
pub struct AnyFrame {
|
||||
ptr: *const MetaSlot,
|
||||
}
|
||||
impl<M: FrameMeta> TryFrom<Frame<dyn FrameMeta>> for Frame<M> {
|
||||
type Error = Frame<dyn FrameMeta>;
|
||||
|
||||
unsafe impl Send for AnyFrame {}
|
||||
unsafe impl Sync for AnyFrame {}
|
||||
|
||||
impl AnyFrame {
|
||||
/// Forget the handle to the page.
|
||||
///
|
||||
/// This is the same as [`Frame::into_raw`].
|
||||
///
|
||||
/// This will result in the page being leaked without calling the custom dropper.
|
||||
///
|
||||
/// A physical address to the page is returned in case the page needs to be
|
||||
/// restored using [`Self::from_raw`] later.
|
||||
pub(in crate::mm) fn into_raw(self) -> Paddr {
|
||||
let paddr = self.paddr();
|
||||
core::mem::forget(self);
|
||||
paddr
|
||||
}
|
||||
|
||||
/// Restore a forgotten page from a physical address.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// The safety concerns are the same as [`Frame::from_raw`].
|
||||
pub(in crate::mm) unsafe fn from_raw(paddr: Paddr) -> Self {
|
||||
let vaddr = mapping::page_to_meta::<PagingConsts>(paddr);
|
||||
let ptr = vaddr as *const MetaSlot;
|
||||
|
||||
Self { ptr }
|
||||
}
|
||||
|
||||
/// Get the metadata of this page.
|
||||
pub fn meta(&self) -> &dyn Any {
|
||||
let slot = self.slot();
|
||||
|
||||
// SAFETY: The page metadata is valid to be borrowed immutably, since it will never be
|
||||
// borrowed mutably after initialization.
|
||||
let vtable_ptr = unsafe { &*slot.vtable_ptr.get() };
|
||||
|
||||
// SAFETY: The page metadata is initialized and valid.
|
||||
let vtable_ptr = *unsafe { vtable_ptr.assume_init_ref() };
|
||||
|
||||
let meta_ptr: *const dyn FrameMeta = core::ptr::from_raw_parts(self.ptr, vtable_ptr);
|
||||
|
||||
// SAFETY: `self.ptr` points to the metadata storage which is valid to be immutably
|
||||
// borrowed under `vtable_ptr` because the vtable is correct, it lives under the given
|
||||
// lifetime, and no one will mutably borrow the page metadata after initialization.
|
||||
(unsafe { &*meta_ptr }) as &dyn Any
|
||||
}
|
||||
|
||||
/// Get the physical address of the start of the page
|
||||
pub fn paddr(&self) -> Paddr {
|
||||
mapping::meta_to_page::<PagingConsts>(self.ptr as Vaddr)
|
||||
}
|
||||
|
||||
/// Get the paging level of this page.
|
||||
pub fn level(&self) -> PagingLevel {
|
||||
1
|
||||
}
|
||||
|
||||
/// Size of this page in bytes.
|
||||
pub fn size(&self) -> usize {
|
||||
PAGE_SIZE
|
||||
}
|
||||
|
||||
fn slot(&self) -> &MetaSlot {
|
||||
// SAFETY: `ptr` points to a valid `MetaSlot` that will never be mutably borrowed, so taking an
|
||||
// immutable reference to it is always safe.
|
||||
unsafe { &*self.ptr }
|
||||
}
|
||||
}
|
||||
|
||||
impl<M: FrameMeta> TryFrom<AnyFrame> for Frame<M> {
|
||||
type Error = AnyFrame;
|
||||
|
||||
/// Try converting a [`AnyFrame`] into the statically-typed [`Frame`].
|
||||
/// Try converting a [`Frame<dyn FrameMeta>`] into the statically-typed [`Frame`].
|
||||
///
|
||||
/// If the usage of the page is not the same as the expected usage, it will
|
||||
/// return the dynamic page itself as is.
|
||||
fn try_from(dyn_page: AnyFrame) -> Result<Self, Self::Error> {
|
||||
if dyn_page.meta().is::<M>() {
|
||||
fn try_from(dyn_frame: Frame<dyn FrameMeta>) -> Result<Self, Self::Error> {
|
||||
if (dyn_frame.dyn_meta() as &dyn core::any::Any).is::<M>() {
|
||||
let result = Frame {
|
||||
ptr: dyn_page.ptr,
|
||||
ptr: dyn_frame.ptr,
|
||||
_marker: PhantomData,
|
||||
};
|
||||
let _ = ManuallyDrop::new(dyn_page);
|
||||
let _ = ManuallyDrop::new(dyn_frame);
|
||||
Ok(result)
|
||||
} else {
|
||||
Err(dyn_page)
|
||||
Err(dyn_frame)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<M: FrameMeta> From<Frame<M>> for AnyFrame {
|
||||
fn from(page: Frame<M>) -> Self {
|
||||
let result = Self { ptr: page.ptr };
|
||||
let _ = ManuallyDrop::new(page);
|
||||
impl<M: FrameMeta> From<Frame<M>> for Frame<dyn FrameMeta> {
|
||||
fn from(frame: Frame<M>) -> Self {
|
||||
let result = Self {
|
||||
ptr: frame.ptr,
|
||||
_marker: PhantomData,
|
||||
};
|
||||
let _ = ManuallyDrop::new(frame);
|
||||
result
|
||||
}
|
||||
}
|
||||
|
||||
impl From<UntypedFrame> for AnyFrame {
|
||||
impl From<UntypedFrame> for Frame<dyn FrameMeta> {
|
||||
fn from(frame: UntypedFrame) -> Self {
|
||||
Frame::<UntypedMeta>::from(frame).into()
|
||||
}
|
||||
}
|
||||
|
||||
impl Clone for AnyFrame {
|
||||
fn clone(&self) -> Self {
|
||||
// SAFETY: We have already held a reference to the page.
|
||||
unsafe { self.slot().inc_ref_count() };
|
||||
|
||||
Self { ptr: self.ptr }
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for AnyFrame {
|
||||
fn drop(&mut self) {
|
||||
let last_ref_cnt = self.slot().ref_count.fetch_sub(1, Ordering::Release);
|
||||
debug_assert!(last_ref_cnt != 0 && last_ref_cnt != REF_COUNT_UNUSED);
|
||||
|
||||
if last_ref_cnt == 1 {
|
||||
// A fence is needed here with the same reasons stated in the implementation of
|
||||
// `Arc::drop`: <https://doc.rust-lang.org/std/sync/struct.Arc.html#method.drop>.
|
||||
core::sync::atomic::fence(Ordering::Acquire);
|
||||
|
||||
// SAFETY: this is the last reference and is about to be dropped.
|
||||
unsafe {
|
||||
meta::drop_last_in_place(self.ptr as *mut MetaSlot);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Increases the reference count of the page by one.
|
||||
///
|
||||
/// # Safety
|
||||
|
@ -16,8 +16,8 @@ use core::mem::ManuallyDrop;
|
||||
pub use segment::UntypedSegment;
|
||||
|
||||
use super::{
|
||||
meta::{impl_frame_meta_for, MetaSlot},
|
||||
AnyFrame, Frame,
|
||||
meta::{impl_frame_meta_for, FrameMeta, MetaSlot},
|
||||
Frame,
|
||||
};
|
||||
use crate::{
|
||||
mm::{
|
||||
@ -100,14 +100,14 @@ impl From<Frame<UntypedMeta>> for UntypedFrame {
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<AnyFrame> for UntypedFrame {
|
||||
type Error = AnyFrame;
|
||||
impl TryFrom<Frame<dyn FrameMeta>> for UntypedFrame {
|
||||
type Error = Frame<dyn FrameMeta>;
|
||||
|
||||
/// Try converting a [`AnyFrame`] into the statically-typed [`UntypedFrame`].
|
||||
/// Try converting a [`Frame<dyn FrameMeta>`] into the statically-typed [`UntypedFrame`].
|
||||
///
|
||||
/// If the dynamic page is not used as an untyped page frame, it will
|
||||
/// return the dynamic page itself as is.
|
||||
fn try_from(page: AnyFrame) -> core::result::Result<Self, Self::Error> {
|
||||
fn try_from(page: Frame<dyn FrameMeta>) -> core::result::Result<Self, Self::Error> {
|
||||
page.try_into().map(|p: Frame<UntypedMeta>| p.into())
|
||||
}
|
||||
}
|
||||
|
@ -11,7 +11,7 @@ use super::{KERNEL_PAGE_TABLE, TRACKED_MAPPED_PAGES_RANGE, VMALLOC_VADDR_RANGE};
|
||||
use crate::{
|
||||
cpu::CpuSet,
|
||||
mm::{
|
||||
frame::{meta::FrameMeta, AnyFrame, Frame},
|
||||
frame::{meta::FrameMeta, Frame},
|
||||
page_prop::PageProperty,
|
||||
page_table::PageTableItem,
|
||||
tlb::{TlbFlushOp, TlbFlusher, FLUSH_ALL_RANGE_THRESHOLD},
|
||||
@ -232,7 +232,7 @@ impl KVirtArea<Tracked> {
|
||||
///
|
||||
/// This function returns None if the address is not mapped (`NotMapped`),
|
||||
/// while panics if the address is mapped to a `MappedUntracked` or `PageTableNode` page.
|
||||
pub fn get_page(&self, addr: Vaddr) -> Option<AnyFrame> {
|
||||
pub fn get_page(&self, addr: Vaddr) -> Option<Frame<dyn FrameMeta>> {
|
||||
let query_result = self.query_page(addr);
|
||||
match query_result {
|
||||
PageTableItem::Mapped {
|
||||
|
@ -76,7 +76,9 @@ use super::{
|
||||
};
|
||||
use crate::{
|
||||
mm::{
|
||||
frame::AnyFrame, kspace::should_map_as_tracked, paddr_to_vaddr, Paddr, PageProperty, Vaddr,
|
||||
frame::{meta::FrameMeta, Frame},
|
||||
kspace::should_map_as_tracked,
|
||||
paddr_to_vaddr, Paddr, PageProperty, Vaddr,
|
||||
},
|
||||
task::{disable_preempt, DisabledPreemptGuard},
|
||||
};
|
||||
@ -89,7 +91,7 @@ pub enum PageTableItem {
|
||||
},
|
||||
Mapped {
|
||||
va: Vaddr,
|
||||
page: AnyFrame,
|
||||
page: Frame<dyn FrameMeta>,
|
||||
prop: PageProperty,
|
||||
},
|
||||
#[allow(dead_code)]
|
||||
@ -400,9 +402,9 @@ where
|
||||
self.0.query()
|
||||
}
|
||||
|
||||
/// Maps the range starting from the current address to a [`AnyFrame`].
|
||||
/// Maps the range starting from the current address to a [`Frame<dyn FrameMeta>`].
|
||||
///
|
||||
/// It returns the previously mapped [`AnyFrame`] if that exists.
|
||||
/// It returns the previously mapped [`Frame<dyn FrameMeta>`] if that exists.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
@ -415,7 +417,11 @@ where
|
||||
///
|
||||
/// The caller should ensure that the virtual range being mapped does
|
||||
/// not affect kernel's memory safety.
|
||||
pub unsafe fn map(&mut self, page: AnyFrame, prop: PageProperty) -> Option<AnyFrame> {
|
||||
pub unsafe fn map(
|
||||
&mut self,
|
||||
page: Frame<dyn FrameMeta>,
|
||||
prop: PageProperty,
|
||||
) -> Option<Frame<dyn FrameMeta>> {
|
||||
let end = self.0.va + page.size();
|
||||
assert!(end <= self.0.barrier_va.end);
|
||||
|
||||
|
@ -8,7 +8,7 @@ use super::{MapTrackingStatus, PageTableEntryTrait, RawPageTableNode};
|
||||
use crate::{
|
||||
arch::mm::{PageTableEntry, PagingConsts},
|
||||
mm::{
|
||||
frame::{inc_page_ref_count, AnyFrame},
|
||||
frame::{inc_page_ref_count, meta::FrameMeta, Frame},
|
||||
page_prop::PageProperty,
|
||||
Paddr, PagingConstsTrait, PagingLevel,
|
||||
},
|
||||
@ -27,7 +27,7 @@ pub(in crate::mm) enum Child<
|
||||
[(); C::NR_LEVELS as usize]:,
|
||||
{
|
||||
PageTable(RawPageTableNode<E, C>),
|
||||
Frame(AnyFrame, PageProperty),
|
||||
Frame(Frame<dyn FrameMeta>, PageProperty),
|
||||
/// Pages not tracked by handles.
|
||||
Untracked(Paddr, PagingLevel, PageProperty),
|
||||
None,
|
||||
@ -119,7 +119,7 @@ where
|
||||
match is_tracked {
|
||||
MapTrackingStatus::Tracked => {
|
||||
// SAFETY: The physical address points to a valid page.
|
||||
let page = unsafe { AnyFrame::from_raw(paddr) };
|
||||
let page = unsafe { Frame::<dyn FrameMeta>::from_raw(paddr) };
|
||||
Child::Frame(page, pte.prop())
|
||||
}
|
||||
MapTrackingStatus::Untracked => Child::Untracked(paddr, level, pte.prop()),
|
||||
@ -162,7 +162,7 @@ where
|
||||
// the reference to the page.
|
||||
unsafe { inc_page_ref_count(paddr) };
|
||||
// SAFETY: The physical address points to a valid page.
|
||||
let page = unsafe { AnyFrame::from_raw(paddr) };
|
||||
let page = unsafe { Frame::<dyn FrameMeta>::from_raw(paddr) };
|
||||
Child::Frame(page, pte.prop())
|
||||
}
|
||||
MapTrackingStatus::Untracked => Child::Untracked(paddr, level, pte.prop()),
|
||||
|
@ -40,7 +40,7 @@ use super::{nr_subpage_per_huge, PageTableEntryTrait};
|
||||
use crate::{
|
||||
arch::mm::{PageTableEntry, PagingConsts},
|
||||
mm::{
|
||||
frame::{self, inc_page_ref_count, meta::FrameMeta, AnyFrame, Frame},
|
||||
frame::{self, inc_page_ref_count, meta::FrameMeta, Frame},
|
||||
paddr_to_vaddr, Paddr, PagingConstsTrait, PagingLevel, PAGE_SIZE,
|
||||
},
|
||||
};
|
||||
@ -442,7 +442,7 @@ where
|
||||
} else if is_tracked == MapTrackingStatus::Tracked {
|
||||
// SAFETY: The PTE points to a tracked page. The ownership
|
||||
// of the child is transferred to the child then dropped.
|
||||
drop(unsafe { AnyFrame::from_raw(paddr) });
|
||||
drop(unsafe { Frame::<dyn FrameMeta>::from_raw(paddr) });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -5,7 +5,10 @@
|
||||
use alloc::vec::Vec;
|
||||
use core::ops::Range;
|
||||
|
||||
use super::{frame::AnyFrame, Vaddr, PAGE_SIZE};
|
||||
use super::{
|
||||
frame::{meta::FrameMeta, Frame},
|
||||
Vaddr, PAGE_SIZE,
|
||||
};
|
||||
use crate::{
|
||||
cpu::{CpuSet, PinCurrentCpu},
|
||||
cpu_local,
|
||||
@ -77,7 +80,7 @@ impl<G: PinCurrentCpu> TlbFlusher<G> {
|
||||
/// flushed. Otherwise if the page is recycled for other purposes, the user
|
||||
/// space program can still access the page through the TLB entries. This
|
||||
/// method is designed to be used in such cases.
|
||||
pub fn issue_tlb_flush_with(&self, op: TlbFlushOp, drop_after_flush: AnyFrame) {
|
||||
pub fn issue_tlb_flush_with(&self, op: TlbFlushOp, drop_after_flush: Frame<dyn FrameMeta>) {
|
||||
self.issue_tlb_flush_(op, Some(drop_after_flush));
|
||||
}
|
||||
|
||||
@ -91,7 +94,7 @@ impl<G: PinCurrentCpu> TlbFlusher<G> {
|
||||
self.need_self_flush
|
||||
}
|
||||
|
||||
fn issue_tlb_flush_(&self, op: TlbFlushOp, drop_after_flush: Option<AnyFrame>) {
|
||||
fn issue_tlb_flush_(&self, op: TlbFlushOp, drop_after_flush: Option<Frame<dyn FrameMeta>>) {
|
||||
let op = op.optimize_for_large_range();
|
||||
|
||||
// Fast path for single CPU cases.
|
||||
@ -156,7 +159,7 @@ impl TlbFlushOp {
|
||||
// Lock ordering: lock FLUSH_OPS before PAGE_KEEPER.
|
||||
cpu_local! {
|
||||
static FLUSH_OPS: SpinLock<OpsStack, LocalIrqDisabled> = SpinLock::new(OpsStack::new());
|
||||
static PAGE_KEEPER: SpinLock<Vec<AnyFrame>, LocalIrqDisabled> = SpinLock::new(Vec::new());
|
||||
static PAGE_KEEPER: SpinLock<Vec<Frame<dyn FrameMeta>>, LocalIrqDisabled> = SpinLock::new(Vec::new());
|
||||
}
|
||||
|
||||
fn do_remote_flush() {
|
||||
|
Reference in New Issue
Block a user