x86_64/structures/paging/
frame.rsuse super::page::AddressNotAligned;
use crate::structures::paging::page::{PageSize, Size4KiB};
use crate::PhysAddr;
use core::fmt;
use core::marker::PhantomData;
use core::ops::{Add, AddAssign, Sub, SubAssign};
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[repr(C)]
pub struct PhysFrame<S: PageSize = Size4KiB> {
pub(crate) start_address: PhysAddr,
size: PhantomData<S>,
}
impl<S: PageSize> PhysFrame<S> {
#[inline]
pub fn from_start_address(address: PhysAddr) -> Result<Self, AddressNotAligned> {
if !address.is_aligned(S::SIZE) {
return Err(AddressNotAligned);
}
Ok(unsafe { PhysFrame::from_start_address_unchecked(address) })
}
#[inline]
#[rustversion::attr(since(1.61), const)]
pub unsafe fn from_start_address_unchecked(start_address: PhysAddr) -> Self {
PhysFrame {
start_address,
size: PhantomData,
}
}
#[inline]
pub fn containing_address(address: PhysAddr) -> Self {
PhysFrame {
start_address: address.align_down(S::SIZE),
size: PhantomData,
}
}
#[inline]
#[rustversion::attr(since(1.61), const)]
pub fn start_address(self) -> PhysAddr {
self.start_address
}
#[inline]
#[rustversion::attr(since(1.61), const)]
pub fn size(self) -> u64 {
S::SIZE
}
#[inline]
#[rustversion::attr(since(1.61), const)]
pub fn range(start: PhysFrame<S>, end: PhysFrame<S>) -> PhysFrameRange<S> {
PhysFrameRange { start, end }
}
#[inline]
#[rustversion::attr(since(1.61), const)]
pub fn range_inclusive(start: PhysFrame<S>, end: PhysFrame<S>) -> PhysFrameRangeInclusive<S> {
PhysFrameRangeInclusive { start, end }
}
}
impl<S: PageSize> fmt::Debug for PhysFrame<S> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.write_fmt(format_args!(
"PhysFrame[{}]({:#x})",
S::DEBUG_STR,
self.start_address().as_u64()
))
}
}
impl<S: PageSize> Add<u64> for PhysFrame<S> {
type Output = Self;
#[inline]
fn add(self, rhs: u64) -> Self::Output {
PhysFrame::containing_address(self.start_address() + rhs * S::SIZE)
}
}
impl<S: PageSize> AddAssign<u64> for PhysFrame<S> {
#[inline]
fn add_assign(&mut self, rhs: u64) {
*self = *self + rhs;
}
}
impl<S: PageSize> Sub<u64> for PhysFrame<S> {
type Output = Self;
#[inline]
fn sub(self, rhs: u64) -> Self::Output {
PhysFrame::containing_address(self.start_address() - rhs * S::SIZE)
}
}
impl<S: PageSize> SubAssign<u64> for PhysFrame<S> {
#[inline]
fn sub_assign(&mut self, rhs: u64) {
*self = *self - rhs;
}
}
impl<S: PageSize> Sub<PhysFrame<S>> for PhysFrame<S> {
type Output = u64;
#[inline]
fn sub(self, rhs: PhysFrame<S>) -> Self::Output {
(self.start_address - rhs.start_address) / S::SIZE
}
}
#[derive(Clone, Copy, PartialEq, Eq, Hash)]
#[repr(C)]
pub struct PhysFrameRange<S: PageSize = Size4KiB> {
pub start: PhysFrame<S>,
pub end: PhysFrame<S>,
}
impl<S: PageSize> PhysFrameRange<S> {
#[inline]
pub fn is_empty(&self) -> bool {
self.start >= self.end
}
}
impl<S: PageSize> Iterator for PhysFrameRange<S> {
type Item = PhysFrame<S>;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
if self.start < self.end {
let frame = self.start;
self.start += 1;
Some(frame)
} else {
None
}
}
}
impl<S: PageSize> fmt::Debug for PhysFrameRange<S> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_struct("PhysFrameRange")
.field("start", &self.start)
.field("end", &self.end)
.finish()
}
}
#[derive(Clone, Copy, PartialEq, Eq, Hash)]
#[repr(C)]
pub struct PhysFrameRangeInclusive<S: PageSize = Size4KiB> {
pub start: PhysFrame<S>,
pub end: PhysFrame<S>,
}
impl<S: PageSize> PhysFrameRangeInclusive<S> {
#[inline]
pub fn is_empty(&self) -> bool {
self.start > self.end
}
}
impl<S: PageSize> Iterator for PhysFrameRangeInclusive<S> {
type Item = PhysFrame<S>;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
if self.start <= self.end {
let frame = self.start;
self.start += 1;
Some(frame)
} else {
None
}
}
}
impl<S: PageSize> fmt::Debug for PhysFrameRangeInclusive<S> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_struct("PhysFrameRangeInclusive")
.field("start", &self.start)
.field("end", &self.end)
.finish()
}
}