feat(paging): add frame allocator and mapping test
Signed-off-by: Julien CLEMENT <julien.clement@epita.fr>
This commit is contained in:
		
							parent
							
								
									62be6d047e
								
							
						
					
					
						commit
						273b004851
					
				
							
								
								
									
										18
									
								
								Cargo.lock
									
									
									
										generated
									
									
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										18
									
								
								Cargo.lock
									
									
									
										generated
									
									
									
								
							@ -8,6 +8,12 @@ version = "0.10.1"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "dcb6dd1c2376d2e096796e234a70e17e94cc2d5d54ff8ce42b28cef1d0d359a4"
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "bitflags"
 | 
			
		||||
version = "0.4.0"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "8dead7461c1127cf637931a1e50934eb6eee8bff2f74433ac7909e9afcee04a3"
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "bitflags"
 | 
			
		||||
version = "1.3.2"
 | 
			
		||||
@ -19,6 +25,7 @@ name = "julios"
 | 
			
		||||
version = "0.1.0"
 | 
			
		||||
dependencies = [
 | 
			
		||||
 "lazy_static",
 | 
			
		||||
 "multiboot2",
 | 
			
		||||
 "pc-keyboard",
 | 
			
		||||
 "pic8259",
 | 
			
		||||
 "spin",
 | 
			
		||||
@ -35,6 +42,15 @@ dependencies = [
 | 
			
		||||
 "spin",
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "multiboot2"
 | 
			
		||||
version = "0.1.0"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "b209a4456a3cc81fb69ad318ed6d47af81a90b829701f151354e3994d8b216d4"
 | 
			
		||||
dependencies = [
 | 
			
		||||
 "bitflags 0.4.0",
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "pc-keyboard"
 | 
			
		||||
version = "0.5.1"
 | 
			
		||||
@ -75,6 +91,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "bbc6ed1ed2cd4536b083c34041aff7b84448ee25ac4aa5e9d54802ce226f9815"
 | 
			
		||||
dependencies = [
 | 
			
		||||
 "bit_field",
 | 
			
		||||
 "bitflags",
 | 
			
		||||
 "bitflags 1.3.2",
 | 
			
		||||
 "volatile 0.4.4",
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
@ -14,6 +14,7 @@ spin = "0.5.2"
 | 
			
		||||
x86_64 = "0.14.2"
 | 
			
		||||
pic8259 = "0.10.1"
 | 
			
		||||
pc-keyboard = "0.5.0"
 | 
			
		||||
multiboot2 = "0.1.0"
 | 
			
		||||
 | 
			
		||||
[dependencies.lazy_static]
 | 
			
		||||
version = "1.0"
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										2
									
								
								Makefile
									
									
									
									
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										2
									
								
								Makefile
									
									
									
									
									
								
							@ -12,7 +12,7 @@ GRUB_CFG = grub/grub.cfg
 | 
			
		||||
all: $(ISO)
 | 
			
		||||
 | 
			
		||||
run: $(ISO)
 | 
			
		||||
	qemu-system-x86_64 -cdrom $< -serial stdio
 | 
			
		||||
	qemu-system-x86_64 -cdrom $< -serial stdio -m 8G
 | 
			
		||||
 | 
			
		||||
debug: $(ISO)
 | 
			
		||||
	bochs -q
 | 
			
		||||
 | 
			
		||||
@ -15,6 +15,7 @@ bits 32
 | 
			
		||||
 | 
			
		||||
_start:
 | 
			
		||||
    mov esp, stack_top
 | 
			
		||||
    mov edi, ebx
 | 
			
		||||
 | 
			
		||||
    call check_multiboot
 | 
			
		||||
    call check_cpuid
 | 
			
		||||
@ -27,6 +28,11 @@ _start:
 | 
			
		||||
    jmp gdt64.code:long_mode_start
 | 
			
		||||
 | 
			
		||||
set_up_page_tables:
 | 
			
		||||
    ; recursively map p4
 | 
			
		||||
    mov eax, p4_table
 | 
			
		||||
    or eax, 0b11 ; present + writeable
 | 
			
		||||
    mov [p4_table + 511 * 8], eax
 | 
			
		||||
 | 
			
		||||
    ; map first P4 entry to P3 table
 | 
			
		||||
    mov eax, p3_table
 | 
			
		||||
    or eax, 0b11 ; present + writable
 | 
			
		||||
@ -163,9 +169,8 @@ p3_table:
 | 
			
		||||
p2_table:
 | 
			
		||||
    resb 4096
 | 
			
		||||
 | 
			
		||||
section .stack
 | 
			
		||||
stack_bottom:
 | 
			
		||||
    resb 0x800000
 | 
			
		||||
    resb 4 * 4096
 | 
			
		||||
stack_top:
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -1,4 +1,5 @@
 | 
			
		||||
use crate::gdt;
 | 
			
		||||
use crate::hlt_loop;
 | 
			
		||||
use crate::vga::{self, Color, ColorCode};
 | 
			
		||||
use crate::{print, println};
 | 
			
		||||
use lazy_static::lazy_static;
 | 
			
		||||
@ -6,6 +7,7 @@ use pc_keyboard::{layouts, DecodedKey, HandleControl, Keyboard, ScancodeSet1};
 | 
			
		||||
use pic8259::ChainedPics;
 | 
			
		||||
use spin::{self, Mutex};
 | 
			
		||||
use x86_64::instructions::port::Port;
 | 
			
		||||
use x86_64::structures::idt::PageFaultErrorCode;
 | 
			
		||||
use x86_64::structures::idt::{InterruptDescriptorTable, InterruptStackFrame};
 | 
			
		||||
 | 
			
		||||
pub const PIC_1_OFFSET: u8 = 32;
 | 
			
		||||
@ -37,6 +39,7 @@ lazy_static! {
 | 
			
		||||
    static ref IDT: InterruptDescriptorTable = {
 | 
			
		||||
        let mut idt = InterruptDescriptorTable::new();
 | 
			
		||||
        idt.breakpoint.set_handler_fn(breakpoint_handler);
 | 
			
		||||
        idt.page_fault.set_handler_fn(page_fault_handler);
 | 
			
		||||
        unsafe {
 | 
			
		||||
            idt.double_fault
 | 
			
		||||
                .set_handler_fn(double_fault_handler)
 | 
			
		||||
@ -66,6 +69,22 @@ extern "x86-interrupt" fn breakpoint_handler(stack_frame: InterruptStackFrame) {
 | 
			
		||||
    vga::change_color(color);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
extern "x86-interrupt" fn page_fault_handler(
 | 
			
		||||
    stack_frame: InterruptStackFrame,
 | 
			
		||||
    error_code: PageFaultErrorCode,
 | 
			
		||||
) {
 | 
			
		||||
    let color: vga::ColorCode = vga::get_color();
 | 
			
		||||
    vga::change_color(ColorCode::new(Color::LightRed, Color::Black));
 | 
			
		||||
    use x86_64::registers::control::Cr2;
 | 
			
		||||
 | 
			
		||||
    println!("EXCEPTION: PAGE FAULT");
 | 
			
		||||
    println!("Accessed Address: {:?}", Cr2::read());
 | 
			
		||||
    println!("Error Code: {:?}", error_code);
 | 
			
		||||
    println!("{:#?}", stack_frame);
 | 
			
		||||
    vga::change_color(color);
 | 
			
		||||
    hlt_loop();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
extern "x86-interrupt" fn double_fault_handler(
 | 
			
		||||
    stack_frame: InterruptStackFrame,
 | 
			
		||||
    _error_code: u64,
 | 
			
		||||
@ -74,7 +93,7 @@ extern "x86-interrupt" fn double_fault_handler(
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
extern "x86-interrupt" fn timer_interrupt_handler(_stack_frame: InterruptStackFrame) {
 | 
			
		||||
    print!(".");
 | 
			
		||||
    // print!(".");
 | 
			
		||||
    unsafe {
 | 
			
		||||
        PICS.lock()
 | 
			
		||||
            .notify_end_of_interrupt(InterruptIndex::Timer.as_u8());
 | 
			
		||||
@ -83,10 +102,9 @@ extern "x86-interrupt" fn timer_interrupt_handler(_stack_frame: InterruptStackFr
 | 
			
		||||
 | 
			
		||||
extern "x86-interrupt" fn keyboard_interrupt_handler(_stack_frame: InterruptStackFrame) {
 | 
			
		||||
    lazy_static! {
 | 
			
		||||
        static ref KEYBOARD: Mutex<Keyboard<layouts::Us104Key, ScancodeSet1>> =
 | 
			
		||||
            Mutex::new(Keyboard::new(layouts::Us104Key, ScancodeSet1,
 | 
			
		||||
                HandleControl::Ignore)
 | 
			
		||||
            );
 | 
			
		||||
        static ref KEYBOARD: Mutex<Keyboard<layouts::Us104Key, ScancodeSet1>> = Mutex::new(
 | 
			
		||||
            Keyboard::new(layouts::Us104Key, ScancodeSet1, HandleControl::Ignore)
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    let mut keyboard = KEYBOARD.lock();
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										35
									
								
								src/lib.rs
									
									
									
									
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										35
									
								
								src/lib.rs
									
									
									
									
									
								
							@ -4,9 +4,12 @@
 | 
			
		||||
 | 
			
		||||
mod gdt;
 | 
			
		||||
mod interrupts;
 | 
			
		||||
mod memory;
 | 
			
		||||
mod serial;
 | 
			
		||||
mod vga;
 | 
			
		||||
 | 
			
		||||
extern crate multiboot2;
 | 
			
		||||
 | 
			
		||||
use core::panic::PanicInfo;
 | 
			
		||||
use vga::{Color, ColorCode};
 | 
			
		||||
 | 
			
		||||
@ -31,11 +34,39 @@ pub fn init() {
 | 
			
		||||
    vga::change_color(ColorCode::new(Color::LightGreen, Color::Black));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn get_frame_allocator(multiboot_info_addr: usize) -> memory::AreaFrameAllocator {
 | 
			
		||||
    let boot_info = unsafe { multiboot2::load(multiboot_info_addr) };
 | 
			
		||||
    let memory_map_tag = boot_info.memory_map_tag().expect("Memory map tag required");
 | 
			
		||||
 | 
			
		||||
    let elf_sections_tag = boot_info
 | 
			
		||||
        .elf_sections_tag()
 | 
			
		||||
        .expect("Elf-sections tag required");
 | 
			
		||||
 | 
			
		||||
    let kernel_start: u64 = elf_sections_tag.sections().map(|s| s.addr).min().unwrap();
 | 
			
		||||
    let kernel_end: u64 = elf_sections_tag
 | 
			
		||||
        .sections()
 | 
			
		||||
        .map(|s| s.addr + s.size)
 | 
			
		||||
        .max()
 | 
			
		||||
        .unwrap();
 | 
			
		||||
 | 
			
		||||
    let multiboot_start: u64 = multiboot_info_addr as u64;
 | 
			
		||||
    let multiboot_end: u64 = multiboot_start + (boot_info.total_size as u64);
 | 
			
		||||
 | 
			
		||||
    memory::AreaFrameAllocator::new( kernel_start, kernel_end, multiboot_start,
 | 
			
		||||
        multiboot_end, memory_map_tag.memory_areas())
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[no_mangle]
 | 
			
		||||
pub extern "C" fn julios_main() -> ! {
 | 
			
		||||
pub extern "C" fn julios_main(multiboot_info_addr: usize) -> ! {
 | 
			
		||||
    let boot_info = unsafe { multiboot2::load(multiboot_info_addr) };
 | 
			
		||||
 | 
			
		||||
    let mut frame_allocator = get_frame_allocator(multiboot_info_addr);
 | 
			
		||||
 | 
			
		||||
    memory::kernel_remap(&mut frame_allocator, boot_info);
 | 
			
		||||
 | 
			
		||||
    init();
 | 
			
		||||
    println!("***JuliOS V0.1.0***");
 | 
			
		||||
    serial_println!("Hello serial");
 | 
			
		||||
 | 
			
		||||
    memory::paging::test_paging(&mut frame_allocator);
 | 
			
		||||
    panic!("Kernel end of flow");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -1,26 +1,53 @@
 | 
			
		||||
ENTRY(_start)
 | 
			
		||||
 | 
			
		||||
SECTIONS {
 | 
			
		||||
    . = 1M;
 | 
			
		||||
 | 
			
		||||
    .boot :
 | 
			
		||||
    .rodata :
 | 
			
		||||
    {
 | 
			
		||||
        /* ensure that the multiboot header is at the beginning */
 | 
			
		||||
        *(.multiboot_header)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    .stack :
 | 
			
		||||
    {
 | 
			
		||||
        *(.stack)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    .bss :
 | 
			
		||||
    {
 | 
			
		||||
        *(.bss)
 | 
			
		||||
        KEEP(*(.multiboot_header))
 | 
			
		||||
        *(.rodata .rodata.*)
 | 
			
		||||
        . = ALIGN(4K);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    .text :
 | 
			
		||||
    {
 | 
			
		||||
        *(.text)
 | 
			
		||||
        *(.text .text.*)
 | 
			
		||||
        . = ALIGN(4K);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    .data :
 | 
			
		||||
    {
 | 
			
		||||
        *(.data .data.*)
 | 
			
		||||
        . = ALIGN(4K);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    .bss :
 | 
			
		||||
    {
 | 
			
		||||
        *(.bss .bss.*)
 | 
			
		||||
        . = ALIGN(4K);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    .got :
 | 
			
		||||
    {
 | 
			
		||||
        *(.got)
 | 
			
		||||
        . = ALIGN(4K);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    .got.plt :
 | 
			
		||||
    {
 | 
			
		||||
        *(.got.plt)
 | 
			
		||||
        . = ALIGN(4K);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    .data.rel.ro : ALIGN(4K) {
 | 
			
		||||
        *(.data.rel.ro.local*) *(.data.rel.ro .data.rel.ro.*)
 | 
			
		||||
        . = ALIGN(4K);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    .gcc_except_table : ALIGN(4K) {
 | 
			
		||||
        *(.gcc_except_table)
 | 
			
		||||
        . = ALIGN(4K);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										94
									
								
								src/memory/frame_allocator.rs
									
									
									
									
									
										Normal file
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										94
									
								
								src/memory/frame_allocator.rs
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,94 @@
 | 
			
		||||
pub use super::PAGE_SIZE;
 | 
			
		||||
use multiboot2::{MemoryArea, MemoryAreaIter};
 | 
			
		||||
pub use x86_64::structures::paging::{
 | 
			
		||||
    frame::PhysFrame as Frame, FrameAllocator, FrameDeallocator, Size4KiB,
 | 
			
		||||
};
 | 
			
		||||
use x86_64::PhysAddr;
 | 
			
		||||
 | 
			
		||||
pub struct AreaFrameAllocator {
 | 
			
		||||
    next_free_frame: Frame,
 | 
			
		||||
    current_area: Option<&'static MemoryArea>,
 | 
			
		||||
    areas: MemoryAreaIter,
 | 
			
		||||
    kernel_start: Frame,
 | 
			
		||||
    kernel_end: Frame,
 | 
			
		||||
    multiboot_start: Frame,
 | 
			
		||||
    multiboot_end: Frame,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl AreaFrameAllocator {
 | 
			
		||||
    pub fn new(kernel_start: u64, kernel_end: u64, multiboot_start: u64, multiboot_end: u64, memory_areas: MemoryAreaIter) -> AreaFrameAllocator {
 | 
			
		||||
        let mut allocator = AreaFrameAllocator {
 | 
			
		||||
            next_free_frame: Frame::containing_address(PhysAddr::new(0)),
 | 
			
		||||
            current_area: None,
 | 
			
		||||
            areas: memory_areas,
 | 
			
		||||
            kernel_start: Frame::containing_address(PhysAddr::new(kernel_start)),
 | 
			
		||||
            kernel_end: Frame::containing_address(PhysAddr::new(kernel_end)),
 | 
			
		||||
            multiboot_start: Frame::containing_address(PhysAddr::new(multiboot_start)),
 | 
			
		||||
            multiboot_end: Frame::containing_address(PhysAddr::new(multiboot_end)),
 | 
			
		||||
        };
 | 
			
		||||
        allocator.choose_next_area();
 | 
			
		||||
        allocator
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn choose_next_area(&mut self) {
 | 
			
		||||
        self.current_area = self
 | 
			
		||||
            .areas
 | 
			
		||||
            .clone()
 | 
			
		||||
            .filter(|area| {
 | 
			
		||||
                let address = area.base_addr + area.length - 1;
 | 
			
		||||
                Frame::containing_address(PhysAddr::new(address)) >= self.next_free_frame
 | 
			
		||||
            })
 | 
			
		||||
        .min_by_key(|area| area.base_addr);
 | 
			
		||||
 | 
			
		||||
        if let Some(area) = self.current_area {
 | 
			
		||||
            let start_frame = Frame::containing_address(PhysAddr::new(area.base_addr));
 | 
			
		||||
            if self.next_free_frame < start_frame {
 | 
			
		||||
                self.next_free_frame = start_frame;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
unsafe impl FrameAllocator<Size4KiB> for AreaFrameAllocator {
 | 
			
		||||
    fn allocate_frame(&mut self) -> Option<Frame> {
 | 
			
		||||
        if let Some(area) = self.current_area {
 | 
			
		||||
            // "Clone" the frame to return it if it's free. Frame doesn't
 | 
			
		||||
            // implement Clone, but we can construct an identical frame.
 | 
			
		||||
            let frame = Frame::containing_address(self.next_free_frame.start_address());
 | 
			
		||||
 | 
			
		||||
            // the last frame of the current area
 | 
			
		||||
            let current_area_last_frame = {
 | 
			
		||||
                let address = area.base_addr + area.length - 1;
 | 
			
		||||
                Frame::containing_address(PhysAddr::new(address))
 | 
			
		||||
            };
 | 
			
		||||
 | 
			
		||||
            if frame > current_area_last_frame {
 | 
			
		||||
                // all frames of current area are used, switch to next area
 | 
			
		||||
                self.choose_next_area();
 | 
			
		||||
            } else if frame >= self.kernel_start && frame <= self.kernel_end {
 | 
			
		||||
                // `frame` is used by the kernel
 | 
			
		||||
                self.next_free_frame =
 | 
			
		||||
                    Frame::containing_address(self.kernel_end.start_address() + PAGE_SIZE);
 | 
			
		||||
            } else if frame >= self.multiboot_start && frame <= self.multiboot_end {
 | 
			
		||||
                // `frame` is used by the multiboot information structure
 | 
			
		||||
                self.next_free_frame =
 | 
			
		||||
                    Frame::containing_address(self.multiboot_end.start_address() + PAGE_SIZE);
 | 
			
		||||
            } else {
 | 
			
		||||
                // frame is unused, increment `next_free_frame` and return it
 | 
			
		||||
                self.next_free_frame =
 | 
			
		||||
                    Frame::containing_address(self.next_free_frame.start_address() + PAGE_SIZE);
 | 
			
		||||
                return Some(frame);
 | 
			
		||||
            }
 | 
			
		||||
            // `frame` was not valid, try it again with the updated `next_free_frame`
 | 
			
		||||
            self.allocate_frame()
 | 
			
		||||
        } else {
 | 
			
		||||
            None // no free frames left
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl FrameDeallocator<Size4KiB> for AreaFrameAllocator {
 | 
			
		||||
    unsafe fn deallocate_frame(&mut self, _frame: Frame) {
 | 
			
		||||
        unimplemented!()
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										7
									
								
								src/memory/mod.rs
									
									
									
									
									
										Normal file
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										7
									
								
								src/memory/mod.rs
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,7 @@
 | 
			
		||||
pub use self::frame_allocator::AreaFrameAllocator;
 | 
			
		||||
pub use paging::kernel_remap;
 | 
			
		||||
 | 
			
		||||
pub mod frame_allocator;
 | 
			
		||||
pub mod paging;
 | 
			
		||||
 | 
			
		||||
pub const PAGE_SIZE: usize = 4096;
 | 
			
		||||
							
								
								
									
										33
									
								
								src/memory/paging/mod.rs
									
									
									
									
									
										Normal file
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										33
									
								
								src/memory/paging/mod.rs
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,33 @@
 | 
			
		||||
use multiboot2::BootInformation;
 | 
			
		||||
use x86_64::structures::paging::{FrameAllocator, Size4KiB, PageTable, RecursivePageTable, Page, PageTableFlags as Flags, Mapper};
 | 
			
		||||
use crate::println;
 | 
			
		||||
use x86_64::VirtAddr;
 | 
			
		||||
 | 
			
		||||
pub const P4: *mut PageTable = 0o177777_777_777_777_777_0000 as *mut _;
 | 
			
		||||
 | 
			
		||||
pub fn kernel_remap<A>(_allocator: &mut A, _boot_info: &BootInformation)
 | 
			
		||||
    where A: FrameAllocator<Size4KiB>
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub fn test_paging<A>(allocator: &mut A)
 | 
			
		||||
    where A: FrameAllocator<Size4KiB>
 | 
			
		||||
{
 | 
			
		||||
    let mut page_table = unsafe { RecursivePageTable::new(&mut *P4).expect("Could not create Page Table") };
 | 
			
		||||
 | 
			
		||||
    let addr = 42 * 512 * 512 * 4096; // 42th P3 entry
 | 
			
		||||
    let page = Page::containing_address(VirtAddr::new(addr));
 | 
			
		||||
    let frame = allocator.allocate_frame().expect("no more frames");
 | 
			
		||||
    println!("None = , map to {:?}", frame);
 | 
			
		||||
    unsafe { page_table.map_to(page, frame, Flags::PRESENT, allocator).expect("Could not map").flush() };
 | 
			
		||||
    println!("next free frame: {:?}", allocator.allocate_frame());
 | 
			
		||||
 | 
			
		||||
    let page_ptr: *mut u8 = page.start_address().as_mut_ptr();
 | 
			
		||||
    let frame_ptr: *mut u8 = frame.start_address().as_u64() as *mut u8;
 | 
			
		||||
 | 
			
		||||
    unsafe {
 | 
			
		||||
        println!("Page: {:#?}, Frame: {:#?}", *page_ptr, *frame_ptr);
 | 
			
		||||
        *frame_ptr = 42;
 | 
			
		||||
        println!("Page: {:#?}, Frame: {:#?}", *page_ptr, *frame_ptr);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user