<commit_before>mod table;
mod entry;
mod mapper;
mod utils;

pub use self::mapper::{Mapper, active_mapper};

use common::*;
use core::marker::PhantomData;
use core::ptr::Unique;

use super::{UntypedCapability, MemoryBlock,
            FrameCapability};
use self::mapper::{switch_mapper};
use self::table::{PageTable, PageTableLevel4, PageTableLevel3, PageTableLevel2, PageTableLevel1};
use self::utils::{Page};

use x86::controlregs;

pub struct PageTableCapability {
    p4_block: MemoryBlock,
    active_mappable_virtual_start_addr: usize,
    active_mappable_count: usize,
    useless: bool,
}

impl PageTableCapability {
    pub fn p4_block(&self) -> &MemoryBlock {
        &self.p4_block
    }

    fn map_addr(&self, frame_addr: usize, dest_addr: usize, flags: EntryFlags) {
        let page = Page::new(dest_addr);

        unsafe {
            active_mapper().borrow_mut_map(self.p4_block().start_addr(), 1, |p4 : &mut PageTable<PageTableLevel4>, mapper| {
                mapper.borrow_mut_map(p4[page.p4_index()].physical_address().unwrap(), 1, |p3 : &mut PageTable<PageTableLevel3>, mapper| {
                    mapper.borrow_mut_map(p3[page.p3_index()].physical_address().unwrap(), 1, |p2 : &mut PageTable<PageTableLevel2>, mapper| {
                        mapper.borrow_mut_map(p2[page.p2_index()].physical_address().unwrap(), 1, |p1 : &mut PageTable<PageTableLevel1>, mapper| {
                            assert!(p1[page.p1_index()].is_unused());
                            p1[page.p1_index()].set_address(frame_addr, flags | PRESENT);
                        })
                    })
                })
            })
        }
    }

    pub unsafe fn create_tables_and_map_vga_buffer(&mut self, untyped: &mut UntypedCapability) {
        self.create_tables(0xb8000, 1, untyped);
        self.map_addr(0xb8000, 0xb8000, WRITABLE);
    }

    pub fn create_tables(&mut self, dest_addr: usize, count: usize, untyped: &mut UntypedCapability) {
        for i in 0..count {
            let page = Page::new(dest_addr + i * PAGE_SIZE);

            unsafe {
                active_mapper().borrow_mut_map(self.p4_block().start_addr(), 1, |p4 : &mut PageTable<PageTableLevel4>, mapper| {
                    p4.next_table_create(page.p4_index(), untyped, mapper, |p3, untyped, mapper| {
                        p3.next_table_create(page.p3_index(), untyped, mapper, |p2, untyped, mapper| {
                            p2.next_table_create(page.p2_index(), untyped, mapper, |p1, untyped, mapper| { })
                        })
                    })
                });
            }
        }
    }

    pub fn map(&mut self, mut frame: FrameCapability, dest_addr: usize) {
        for i in 0..frame.count() {
            let frame_addr = frame.block().start_addr() + i * PAGE_SIZE;
            let flags = frame.flags();
            self.map_addr(frame_addr, dest_addr + i * PAGE_SIZE, flags);
        }

        unsafe { frame.mark_useless(); }
    }

    pub fn identity_map(&mut self, frame: FrameCapability) {
        let dest_addr = frame.block().start_addr();<commit_msg>WIP: unmapping for paging mod<commit_after>mod table;
mod entry;
mod mapper;
mod utils;

pub use self::mapper::{Mapper, active_mapper};

use common::*;
use core::marker::PhantomData;
use core::ptr::Unique;

use super::{UntypedCapability, MemoryBlock,
            FrameCapability};
use self::mapper::{switch_mapper};
use self::table::{PageTable, PageTableLevel4, PageTableLevel3, PageTableLevel2, PageTableLevel1};
use self::utils::{Page};

use x86::controlregs;

pub struct PageTableCapability {
    p4_block: MemoryBlock,
    active_mappable_virtual_start_addr: usize,
    active_mappable_count: usize,
    useless: bool,
}

impl PageTableCapability {
    pub fn p4_block(&self) -> &MemoryBlock {
        &self.p4_block
    }

    fn map_addr(&self, frame_addr: usize, dest_addr: usize, flags: EntryFlags) {
        let page = Page::new(dest_addr);

        unsafe {
            active_mapper().borrow_mut_map(self.p4_block().start_addr(), 1, |p4 : &mut PageTable<PageTableLevel4>, mapper| {
                mapper.borrow_mut_map(p4[page.p4_index()].physical_address().unwrap(), 1, |p3 : &mut PageTable<PageTableLevel3>, mapper| {
                    mapper.borrow_mut_map(p3[page.p3_index()].physical_address().unwrap(), 1, |p2 : &mut PageTable<PageTableLevel2>, mapper| {
                        mapper.borrow_mut_map(p2[page.p2_index()].physical_address().unwrap(), 1, |p1 : &mut PageTable<PageTableLevel1>, mapper| {
                            assert!(p1[page.p1_index()].is_unused());
                            p1[page.p1_index()].set_address(frame_addr, flags | PRESENT);
                        })
                    })
                })
            })
        }
    }

    fn unmap_addr(&self, dest_addr: usize) -> PhysicalAddress {
        let page = Page::new(dest_addr);

        unsafe {
            let mut frame_addr = None;

            active_mapper().borrow_mut_map(self.p4_block().start_addr(), 1, |p4 : &mut PageTable<PageTableLevel4>, mapper| {
                mapper.borrow_mut_map(p4[page.p4_index()].physical_address().unwrap(), 1, |p3 : &mut PageTable<PageTableLevel3>, mapper| {
                    mapper.borrow_mut_map(p3[page.p3_index()].physical_address().unwrap(), 1, |p2 : &mut PageTable<PageTableLevel2>, mapper| {
                        mapper.borrow_mut_map(p2[page.p2_index()].physical_address().unwrap(), 1, |p1 : &mut PageTable<PageTableLevel1>, mapper| {
                            assert!(!p1[page.p1_index()].is_unused());
                            frame_addr = p1[page.p1_index()].physical_address();
                            p1[page.p1_index()].set_unused();
                        })
                    })
                })
            });

            frame_addr.unwrap()
        }
    }

    pub unsafe fn create_tables_and_map_vga_buffer(&mut self, untyped: &mut UntypedCapability) {
        self.create_tables(0xb8000, 1, untyped);
        self.map_addr(0xb8000, 0xb8000, WRITABLE);
    }

    pub fn create_tables(&mut self, dest_addr: usize, count: usize, untyped: &mut UntypedCapability) {
        for i in 0..count {
            let page = Page::new(dest_addr + i * PAGE_SIZE);

            unsafe {
                active_mapper().borrow_mut_map(self.p4_block().start_addr(), 1, |p4 : &mut PageTable<PageTableLevel4>, mapper| {
                    p4.next_table_create(page.p4_index(), untyped, mapper, |p3, untyped, mapper| {
                        p3.next_table_create(page.p3_index(), untyped, mapper, |p2, untyped, mapper| {
                            p2.next_table_create(page.p2_index(), untyped, mapper, |p1, untyped, mapper| { })
                        })
                    })
                });
            }
        }
    }

    pub fn map(&mut self, mut frame: FrameCapability, dest_addr: usize) {
        for i in 0..frame.count() {
            let frame_addr = frame.block().start_addr() + i * PAGE_SIZE;
            let flags = frame.flags();
            self.map_addr(frame_addr, dest_addr + i * PAGE_SIZE, flags);
        }

        unsafe { frame.mark_useless(); }
    }

    pub fn unmap(&mut self, dest_addr: usize) -> FrameCapability {
        unimplemented!()
    }

    pub fn identity_map(&mut self, frame: FrameCapability) {
        let dest_addr = frame.block().start_addr();
{'fraction_non_alphanumeric': 0.13017510519885978, 'fraction_numerical': 0.02049681009909054, 'mean_word_length': 2.365920511649155, 'pattern_counts': {'":': 0, '<': 17, '<?xml version=': 0, '>': 21, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3671715', 'n_tokens_mistral': 2463, 'n_tokens_neox': 2393, 'n_words': 429}