mirror of
https://github.com/asterinas/asterinas.git
synced 2025-06-22 17:03:23 +00:00
Add support for converting from VmFrame
to VmSegment
This commit is contained in:
committed by
Tate, Hongliang Tian
parent
437ab804f3
commit
e0d92b5203
1
Cargo.lock
generated
1
Cargo.lock
generated
@ -70,6 +70,7 @@ checksum = "d92bec98840b8f03a5ff5413de5293bfcd8bf96467cf5452609f939ec6f5de16"
|
|||||||
name = "aster-block"
|
name = "aster-block"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"align_ext",
|
||||||
"aster-frame",
|
"aster-frame",
|
||||||
"aster-util",
|
"aster-util",
|
||||||
"bitflags 1.3.2",
|
"bitflags 1.3.2",
|
||||||
|
@ -314,17 +314,17 @@ impl Drop for VmFrame {
|
|||||||
/// ```
|
/// ```
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct VmSegment {
|
pub struct VmSegment {
|
||||||
inner: Arc<Inner>,
|
inner: VmSegmentInner,
|
||||||
range: Range<usize>,
|
range: Range<usize>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug, Clone)]
|
||||||
struct Inner {
|
struct VmSegmentInner {
|
||||||
start_frame_index: Paddr,
|
start_frame_index: Arc<Paddr>,
|
||||||
nframes: usize,
|
nframes: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Inner {
|
impl VmSegmentInner {
|
||||||
/// Creates the inner part of 'VmSegment'.
|
/// Creates the inner part of 'VmSegment'.
|
||||||
///
|
///
|
||||||
/// # Safety
|
/// # Safety
|
||||||
@ -333,14 +333,13 @@ impl Inner {
|
|||||||
unsafe fn new(paddr: Paddr, nframes: usize, flags: VmFrameFlags) -> Self {
|
unsafe fn new(paddr: Paddr, nframes: usize, flags: VmFrameFlags) -> Self {
|
||||||
assert_eq!(paddr % PAGE_SIZE, 0);
|
assert_eq!(paddr % PAGE_SIZE, 0);
|
||||||
Self {
|
Self {
|
||||||
start_frame_index: (paddr / PAGE_SIZE).bitor(flags.bits),
|
start_frame_index: Arc::new((paddr / PAGE_SIZE).bitor(flags.bits)),
|
||||||
nframes,
|
nframes,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn start_frame_index(&self) -> usize {
|
fn start_frame_index(&self) -> usize {
|
||||||
self.start_frame_index
|
(*self.start_frame_index).bitand(VmFrameFlags::all().bits().not())
|
||||||
.bitand(VmFrameFlags::all().bits().not())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn start_paddr(&self) -> Paddr {
|
fn start_paddr(&self) -> Paddr {
|
||||||
@ -364,7 +363,7 @@ impl VmSegment {
|
|||||||
/// as part of either a `VmFrame` or `VmSegment`.
|
/// as part of either a `VmFrame` or `VmSegment`.
|
||||||
pub(crate) unsafe fn new(paddr: Paddr, nframes: usize, flags: VmFrameFlags) -> Self {
|
pub(crate) unsafe fn new(paddr: Paddr, nframes: usize, flags: VmFrameFlags) -> Self {
|
||||||
Self {
|
Self {
|
||||||
inner: Arc::new(Inner::new(paddr, nframes, flags)),
|
inner: VmSegmentInner::new(paddr, nframes, flags),
|
||||||
range: 0..nframes,
|
range: 0..nframes,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -407,7 +406,7 @@ impl VmSegment {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn need_dealloc(&self) -> bool {
|
fn need_dealloc(&self) -> bool {
|
||||||
(self.inner.start_frame_index & VmFrameFlags::NEED_DEALLOC.bits()) != 0
|
(*self.inner.start_frame_index & VmFrameFlags::NEED_DEALLOC.bits()) != 0
|
||||||
}
|
}
|
||||||
|
|
||||||
fn start_frame_index(&self) -> usize {
|
fn start_frame_index(&self) -> usize {
|
||||||
@ -459,7 +458,7 @@ impl VmIo for VmSegment {
|
|||||||
|
|
||||||
impl Drop for VmSegment {
|
impl Drop for VmSegment {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
if self.need_dealloc() && Arc::strong_count(&self.inner) == 1 {
|
if self.need_dealloc() && Arc::strong_count(&self.inner.start_frame_index) == 1 {
|
||||||
// Safety: the range of contiguous page frames is valid.
|
// Safety: the range of contiguous page frames is valid.
|
||||||
unsafe {
|
unsafe {
|
||||||
frame_allocator::dealloc_contiguous(
|
frame_allocator::dealloc_contiguous(
|
||||||
@ -471,6 +470,18 @@ impl Drop for VmSegment {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<VmFrame> for VmSegment {
|
||||||
|
fn from(frame: VmFrame) -> Self {
|
||||||
|
Self {
|
||||||
|
inner: VmSegmentInner {
|
||||||
|
start_frame_index: frame.frame_index.clone(),
|
||||||
|
nframes: 1,
|
||||||
|
},
|
||||||
|
range: 0..1,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// VmReader is a reader for reading data from a contiguous range of memory.
|
/// VmReader is a reader for reading data from a contiguous range of memory.
|
||||||
///
|
///
|
||||||
/// # Example
|
/// # Example
|
||||||
|
@ -10,6 +10,7 @@ bitflags = "1.3"
|
|||||||
spin = "0.9.4"
|
spin = "0.9.4"
|
||||||
pod = { git = "https://github.com/asterinas/pod", rev = "d7dba56" }
|
pod = { git = "https://github.com/asterinas/pod", rev = "d7dba56" }
|
||||||
aster-frame = { path = "../../../framework/aster-frame" }
|
aster-frame = { path = "../../../framework/aster-frame" }
|
||||||
|
align_ext = { path = "../../../framework/libs/align_ext" }
|
||||||
aster-util = { path = "../../libs/aster-util" }
|
aster-util = { path = "../../libs/aster-util" }
|
||||||
int-to-c-enum = { path = "../../libs/int-to-c-enum" }
|
int-to-c-enum = { path = "../../libs/int-to-c-enum" }
|
||||||
component = { path = "../../libs/comp-sys/component" }
|
component = { path = "../../libs/comp-sys/component" }
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
// SPDX-License-Identifier: MPL-2.0
|
// SPDX-License-Identifier: MPL-2.0
|
||||||
|
|
||||||
|
use align_ext::AlignExt;
|
||||||
use aster_frame::{
|
use aster_frame::{
|
||||||
sync::WaitQueue,
|
sync::WaitQueue,
|
||||||
vm::{VmFrame, VmReader, VmSegment, VmWriter},
|
vm::{VmFrame, VmReader, VmSegment, VmWriter},
|
||||||
@ -358,29 +359,27 @@ pub enum BioStatus {
|
|||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct BioSegment {
|
pub struct BioSegment {
|
||||||
/// The contiguous pages on which this segment resides.
|
/// The contiguous pages on which this segment resides.
|
||||||
pages: Pages,
|
pages: VmSegment,
|
||||||
/// The offset (in bytes) relative to the first page.
|
/// The starting offset (in bytes) within the first page.
|
||||||
|
/// The offset should always be aligned to the sector size and
|
||||||
|
/// must not exceed the size of a single page.
|
||||||
offset: AlignedUsize<SECTOR_SIZE>,
|
offset: AlignedUsize<SECTOR_SIZE>,
|
||||||
// The length (in bytes), may cross pages.
|
/// The total length (in bytes).
|
||||||
|
/// The length can span multiple pages and should be aligned to
|
||||||
|
/// the sector size.
|
||||||
len: AlignedUsize<SECTOR_SIZE>,
|
len: AlignedUsize<SECTOR_SIZE>,
|
||||||
}
|
}
|
||||||
|
|
||||||
const SECTOR_SIZE: u16 = super::SECTOR_SIZE as u16;
|
const SECTOR_SIZE: u16 = super::SECTOR_SIZE as u16;
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
|
||||||
enum Pages {
|
|
||||||
Frame(VmFrame),
|
|
||||||
Segment(VmSegment),
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> BioSegment {
|
impl<'a> BioSegment {
|
||||||
/// Constructs a new `BioSegment` from `VmSegment`.
|
/// Constructs a new `BioSegment` from `VmSegment`.
|
||||||
pub fn from_segment(segment: VmSegment, offset: usize, len: usize) -> Self {
|
pub fn from_segment(segment: VmSegment, offset: usize, len: usize) -> Self {
|
||||||
assert!(offset + len <= segment.nbytes());
|
assert!(offset + len <= segment.nbytes());
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
pages: Pages::Segment(segment),
|
pages: segment.range(frame_range(&(offset..offset + len))),
|
||||||
offset: AlignedUsize::<SECTOR_SIZE>::new(offset).unwrap(),
|
offset: AlignedUsize::<SECTOR_SIZE>::new(offset % super::BLOCK_SIZE).unwrap(),
|
||||||
len: AlignedUsize::<SECTOR_SIZE>::new(len).unwrap(),
|
len: AlignedUsize::<SECTOR_SIZE>::new(len).unwrap(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -390,7 +389,7 @@ impl<'a> BioSegment {
|
|||||||
assert!(offset + len <= super::BLOCK_SIZE);
|
assert!(offset + len <= super::BLOCK_SIZE);
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
pages: Pages::Frame(frame),
|
pages: VmSegment::from(frame),
|
||||||
offset: AlignedUsize::<SECTOR_SIZE>::new(offset).unwrap(),
|
offset: AlignedUsize::<SECTOR_SIZE>::new(offset).unwrap(),
|
||||||
len: AlignedUsize::<SECTOR_SIZE>::new(len).unwrap(),
|
len: AlignedUsize::<SECTOR_SIZE>::new(len).unwrap(),
|
||||||
}
|
}
|
||||||
@ -406,25 +405,39 @@ impl<'a> BioSegment {
|
|||||||
self.len.value()
|
self.len.value()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns the offset (in bytes) within the first page.
|
||||||
|
pub fn offset(&self) -> usize {
|
||||||
|
self.offset.value()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the contiguous pages on which this segment resides.
|
||||||
|
pub fn pages(&self) -> &VmSegment {
|
||||||
|
&self.pages
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns a reader to read data from it.
|
/// Returns a reader to read data from it.
|
||||||
pub fn reader(&'a self) -> VmReader<'a> {
|
pub fn reader(&'a self) -> VmReader<'a> {
|
||||||
let reader = match &self.pages {
|
self.pages
|
||||||
Pages::Segment(segment) => segment.reader(),
|
.reader()
|
||||||
Pages::Frame(frame) => frame.reader(),
|
.skip(self.offset.value())
|
||||||
};
|
.limit(self.len.value())
|
||||||
reader.skip(self.offset.value()).limit(self.len.value())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns a writer to write data into it.
|
/// Returns a writer to write data into it.
|
||||||
pub fn writer(&'a self) -> VmWriter<'a> {
|
pub fn writer(&'a self) -> VmWriter<'a> {
|
||||||
let writer = match &self.pages {
|
self.pages
|
||||||
Pages::Segment(segment) => segment.writer(),
|
.writer()
|
||||||
Pages::Frame(frame) => frame.writer(),
|
.skip(self.offset.value())
|
||||||
};
|
.limit(self.len.value())
|
||||||
writer.skip(self.offset.value()).limit(self.len.value())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn frame_range(byte_range: &Range<usize>) -> Range<usize> {
|
||||||
|
let start = byte_range.start.align_down(super::BLOCK_SIZE);
|
||||||
|
let end = byte_range.end.align_up(super::BLOCK_SIZE);
|
||||||
|
(start / super::BLOCK_SIZE)..(end / super::BLOCK_SIZE)
|
||||||
|
}
|
||||||
|
|
||||||
/// An aligned unsigned integer number.
|
/// An aligned unsigned integer number.
|
||||||
///
|
///
|
||||||
/// An instance of `AlignedUsize<const N: u16>` is guaranteed to have a value that is a multiple
|
/// An instance of `AlignedUsize<const N: u16>` is guaranteed to have a value that is a multiple
|
||||||
|
Reference in New Issue
Block a user