247 lines
		
	
	
		
			6.1 KiB
		
	
	
	
		
			Rust
		
	
	
	
	
	
			
		
		
	
	
			247 lines
		
	
	
		
			6.1 KiB
		
	
	
	
		
			Rust
		
	
	
	
	
	
| /// Flags to be passed to the MapMemory struct.
 | |
| /// Note that it is an error to have memory be
 | |
| /// writable and not readable.
 | |
| #[derive(Copy, PartialEq, Eq, Clone, PartialOrd, Ord, Hash, Debug)]
 | |
| pub struct MemoryFlags {
 | |
|     bits: usize,
 | |
| }
 | |
| 
 | |
| impl MemoryFlags {
 | |
|     /// Free this memory
 | |
|     pub const FREE: Self = Self { bits: 0b0000_0000 };
 | |
| 
 | |
|     /// Immediately allocate this memory.  Otherwise it will
 | |
|     /// be demand-paged.  This is implicitly set when `phys`
 | |
|     /// is not 0.
 | |
|     pub const VALID: Self = Self { bits: 0b0000_0001 };
 | |
| 
 | |
|     /// Allow the CPU to read from this page.
 | |
|     pub const READ: Self = Self { bits: 0b0000_0010 };
 | |
| 
 | |
|     /// Allow the CPU to write to this page.
 | |
|     pub const WRITE: Self = Self { bits: 0b0000_0100 };
 | |
| 
 | |
|     /// Allow the CPU to execute from this page.
 | |
|     pub const EXECUTE: Self = Self { bits: 0b0000_1000 };
 | |
| 
 | |
|     /// Accessible from user mode
 | |
|     pub const USERMODE: Self = Self { bits: 0b0001_0000 };
 | |
| 
 | |
|     /// Globally-available
 | |
|     pub const GLOBAL: Self = Self { bits: 0b0010_0000 };
 | |
| 
 | |
|     /// Cache access status
 | |
|     pub const ACCESSED: Self = Self { bits: 0b0100_0000 };
 | |
| 
 | |
|     /// Page needs flushing
 | |
|     pub const DIRTY: Self = Self { bits: 0b1000_0000 };
 | |
| 
 | |
|     pub fn bits(&self) -> usize {
 | |
|         self.bits
 | |
|     }
 | |
| 
 | |
|     pub fn from_bits(raw: usize) -> Option<MemoryFlags> {
 | |
|         if raw > 255 {
 | |
|             None
 | |
|         } else {
 | |
|             Some(MemoryFlags { bits: raw })
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     pub fn is_empty(&self) -> bool {
 | |
|         self.bits == 0
 | |
|     }
 | |
| 
 | |
|     pub fn empty() -> MemoryFlags {
 | |
|         MemoryFlags { bits: 0 }
 | |
|     }
 | |
| 
 | |
|     pub fn all() -> MemoryFlags {
 | |
|         MemoryFlags { bits: 255 }
 | |
|     }
 | |
| 
 | |
|     pub fn contains(&self, other: MemoryFlags) -> bool {
 | |
|         (self.bits & other.bits) == other.bits
 | |
|     }
 | |
| }
 | |
| 
 | |
| impl core::fmt::Binary for MemoryFlags {
 | |
|     fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
 | |
|         core::fmt::Binary::fmt(&self.bits, f)
 | |
|     }
 | |
| }
 | |
| 
 | |
| impl core::fmt::Octal for MemoryFlags {
 | |
|     fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
 | |
|         core::fmt::Octal::fmt(&self.bits, f)
 | |
|     }
 | |
| }
 | |
| 
 | |
| impl core::fmt::LowerHex for MemoryFlags {
 | |
|     fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
 | |
|         core::fmt::LowerHex::fmt(&self.bits, f)
 | |
|     }
 | |
| }
 | |
| 
 | |
| impl core::fmt::UpperHex for MemoryFlags {
 | |
|     fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
 | |
|         core::fmt::UpperHex::fmt(&self.bits, f)
 | |
|     }
 | |
| }
 | |
| 
 | |
| impl core::ops::BitOr for MemoryFlags {
 | |
|     type Output = Self;
 | |
| 
 | |
|     /// Returns the union of the two sets of flags.
 | |
|     #[inline]
 | |
|     fn bitor(self, other: MemoryFlags) -> Self {
 | |
|         Self {
 | |
|             bits: self.bits | other.bits,
 | |
|         }
 | |
|     }
 | |
| }
 | |
| 
 | |
| impl core::ops::BitOrAssign for MemoryFlags {
 | |
|     /// Adds the set of flags.
 | |
|     #[inline]
 | |
|     fn bitor_assign(&mut self, other: Self) {
 | |
|         self.bits |= other.bits;
 | |
|     }
 | |
| }
 | |
| 
 | |
| impl core::ops::BitXor for MemoryFlags {
 | |
|     type Output = Self;
 | |
| 
 | |
|     /// Returns the left flags, but with all the right flags toggled.
 | |
|     #[inline]
 | |
|     fn bitxor(self, other: Self) -> Self {
 | |
|         Self {
 | |
|             bits: self.bits ^ other.bits,
 | |
|         }
 | |
|     }
 | |
| }
 | |
| 
 | |
| impl core::ops::BitXorAssign for MemoryFlags {
 | |
|     /// Toggles the set of flags.
 | |
|     #[inline]
 | |
|     fn bitxor_assign(&mut self, other: Self) {
 | |
|         self.bits ^= other.bits;
 | |
|     }
 | |
| }
 | |
| 
 | |
| impl core::ops::BitAnd for MemoryFlags {
 | |
|     type Output = Self;
 | |
| 
 | |
|     /// Returns the intersection between the two sets of flags.
 | |
|     #[inline]
 | |
|     fn bitand(self, other: Self) -> Self {
 | |
|         Self {
 | |
|             bits: self.bits & other.bits,
 | |
|         }
 | |
|     }
 | |
| }
 | |
| 
 | |
| impl core::ops::BitAndAssign for MemoryFlags {
 | |
|     /// Disables all flags disabled in the set.
 | |
|     #[inline]
 | |
|     fn bitand_assign(&mut self, other: Self) {
 | |
|         self.bits &= other.bits;
 | |
|     }
 | |
| }
 | |
| 
 | |
| impl core::ops::Sub for MemoryFlags {
 | |
|     type Output = Self;
 | |
| 
 | |
|     /// Returns the set difference of the two sets of flags.
 | |
|     #[inline]
 | |
|     fn sub(self, other: Self) -> Self {
 | |
|         Self {
 | |
|             bits: self.bits & !other.bits,
 | |
|         }
 | |
|     }
 | |
| }
 | |
| 
 | |
| impl core::ops::SubAssign for MemoryFlags {
 | |
|     /// Disables all flags enabled in the set.
 | |
|     #[inline]
 | |
|     fn sub_assign(&mut self, other: Self) {
 | |
|         self.bits &= !other.bits;
 | |
|     }
 | |
| }
 | |
| 
 | |
| impl core::ops::Not for MemoryFlags {
 | |
|     type Output = Self;
 | |
| 
 | |
|     /// Returns the complement of this set of flags.
 | |
|     #[inline]
 | |
|     fn not(self) -> Self {
 | |
|         Self { bits: !self.bits } & MemoryFlags { bits: 255 }
 | |
|     }
 | |
| }
 | |
| 
 | |
| impl core::fmt::Display for MemoryFlags {
 | |
|     fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
 | |
|         let mut first = true;
 | |
|         if self.contains(MemoryFlags::FREE) {
 | |
|             write!(f, "FREE")?;
 | |
|             first = false;
 | |
|         }
 | |
|         if self.contains(MemoryFlags::VALID) {
 | |
|             if !first {
 | |
|                 write!(f, " | ")?;
 | |
|             }
 | |
|             write!(f, "VALID")?;
 | |
|             first = false;
 | |
|         }
 | |
|         if self.contains(MemoryFlags::READ) {
 | |
|             if !first {
 | |
|                 write!(f, " | ")?;
 | |
|             }
 | |
|             write!(f, "READ")?;
 | |
|             first = false;
 | |
|         }
 | |
|         if self.contains(MemoryFlags::WRITE) {
 | |
|             if !first {
 | |
|                 write!(f, " | ")?;
 | |
|             }
 | |
|             write!(f, "WRITE")?;
 | |
|             first = false;
 | |
|         }
 | |
|         if self.contains(MemoryFlags::EXECUTE) {
 | |
|             if !first {
 | |
|                 write!(f, " | ")?;
 | |
|             }
 | |
|             write!(f, "EXECUTE")?;
 | |
|             first = false;
 | |
|         }
 | |
|         if self.contains(MemoryFlags::USERMODE) {
 | |
|             if !first {
 | |
|                 write!(f, " | ")?;
 | |
|             }
 | |
|             write!(f, "USERMODE")?;
 | |
|             first = false;
 | |
|         }
 | |
|         if self.contains(MemoryFlags::GLOBAL) {
 | |
|             if !first {
 | |
|                 write!(f, " | ")?;
 | |
|             }
 | |
|             write!(f, "GLOBAL")?;
 | |
|             first = false;
 | |
|         }
 | |
|         if self.contains(MemoryFlags::ACCESSED) {
 | |
|             if !first {
 | |
|                 write!(f, " | ")?;
 | |
|             }
 | |
|             write!(f, "ACCESSED")?;
 | |
|             first = false;
 | |
|         }
 | |
|         if self.contains(MemoryFlags::DIRTY) {
 | |
|             if !first {
 | |
|                 write!(f, " | ")?;
 | |
|             }
 | |
|             write!(f, "DIRTY")?;
 | |
|         }
 | |
|         Ok(())
 | |
|     }
 | |
| }
 |