1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
use crate::mem::PhysicalAddress;
use core::fmt::{Debug, Formatter, Error};
use super::super::super::hierarchical_table::{HierarchicalEntry, PageState};
use super::super::super::MappingAccessRights;
bitflags! {
    
    pub struct I386EntryFlags: u32 {
        const PRESENT =         1 << 0;
        const WRITABLE =        1 << 1;
        const USER_ACCESSIBLE = 1 << 2;
        const WRITE_THROUGH =   1 << 3;
        const NO_CACHE =        1 << 4;
        const ACCESSED =        1 << 5;
        const DIRTY =           1 << 6;
        const HUGE_PAGE =       1 << 7;
        const GLOBAL =          1 << 8;
        const GUARD_PAGE =      1 << 9;     
        const USER_DEFINED_2 =  1 << 10;    
        const USER_DEFINED_3 =  1 << 11;    
    }
}
impl From<MappingAccessRights> for I386EntryFlags {
    fn from(flags: MappingAccessRights) -> I386EntryFlags {
        let mut newflags = I386EntryFlags::empty();
        
        
        
        if flags.intersects(MappingAccessRights::READABLE | MappingAccessRights::WRITABLE | MappingAccessRights::EXECUTABLE) {
            newflags |= I386EntryFlags::PRESENT
        } else {
            
            return I386EntryFlags::GUARD_PAGE;
        }
        if flags.contains(MappingAccessRights::WRITABLE) {
            newflags |= I386EntryFlags::WRITABLE
        };
        if flags.contains(MappingAccessRights::USER_ACCESSIBLE) {
            newflags |= I386EntryFlags::USER_ACCESSIBLE
        };
        newflags
    }
}
const ENTRY_PHYS_ADDRESS_MASK: usize = 0xffff_f000;
#[repr(transparent)]
#[derive(Clone, Copy)]
pub struct I386Entry(u32);
impl Debug for I386Entry {
    fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> {
        f.debug_struct("Entry")
            .field("flags", &self.flags())
            .field("frame", &self.pointed_frame().as_option())
            .finish()
    }
}
impl HierarchicalEntry for I386Entry {
    type EntryFlagsType = I386EntryFlags;
    
    fn is_unused(&self) -> bool { self.0 == 0 }
    
    fn set_unused(&mut self) -> PageState<PhysicalAddress> {
        let ret = self.pointed_frame();
        self.0 = 0;
        ret
    }
    
    fn is_guard(&self) -> bool { self.flags().contains(I386EntryFlags::GUARD_PAGE) }
    
    fn flags(&self) -> I386EntryFlags { I386EntryFlags::from_bits_truncate(self.0) }
    
    fn pointed_frame(&self) -> PageState<PhysicalAddress> {
        if self.flags().contains(I386EntryFlags::PRESENT) {
            let frame_phys_addr = self.0 as usize & ENTRY_PHYS_ADDRESS_MASK;
            PageState::Present(PhysicalAddress(frame_phys_addr))
        } else if self.flags().contains(I386EntryFlags::GUARD_PAGE) {
            PageState::Guarded
        } else {
            PageState::Available
        }
    }
    
    fn set(&mut self, frame_phys_addr: PhysicalAddress, flags: I386EntryFlags) {
        assert_eq!(flags.contains(I386EntryFlags::PRESENT)
                && flags.contains(I386EntryFlags::GUARD_PAGE), false,
                "a GUARD_PAGE cannot also be PRESENT");
        if flags.contains(I386EntryFlags::GUARD_PAGE) {
            
            self.set_guard();
            return;
        }
        assert_eq!(frame_phys_addr.addr() & !ENTRY_PHYS_ADDRESS_MASK, 0);
        self.0 = (frame_phys_addr.addr() as u32) | flags.bits();
    }
    
    fn set_guard(&mut self) {
        self.0 = 0x00000000 | I386EntryFlags::GUARD_PAGE.bits;
    }
}