Merge pull request #569 from phil-opp/post-10-new

Update post-10 branch for new "Paging Implementation" post
This commit is contained in:
Philipp Oppermann
2019-03-14 10:49:55 +01:00
committed by GitHub
5 changed files with 74 additions and 33 deletions

22
Cargo.lock generated
View File

@@ -31,7 +31,7 @@ name = "blog_os"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"array-init 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", "array-init 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
"bootloader 0.3.12 (registry+https://github.com/rust-lang/crates.io-index)", "bootloader 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"pc-keyboard 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "pc-keyboard 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
"pic8259_simple 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "pic8259_simple 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -43,13 +43,13 @@ dependencies = [
[[package]] [[package]]
name = "bootloader" name = "bootloader"
version = "0.3.12" version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ dependencies = [
"fixedvec 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "fixedvec 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
"font8x8 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", "font8x8 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
"usize_conversions 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "usize_conversions 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"x86_64 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)", "x86_64 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
"xmas-elf 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", "xmas-elf 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
@@ -297,6 +297,19 @@ dependencies = [
"ux 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "ux 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]]
name = "x86_64"
version = "0.3.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"array-init 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
"bit_field 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
"bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
"os_bootinfo 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"usize_conversions 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"ux 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]] [[package]]
name = "x86_64" name = "x86_64"
version = "0.5.2" version = "0.5.2"
@@ -328,7 +341,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
"checksum array-init 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "23589ecb866b460d3a0f1278834750268c607e8e28a1b982c907219f3178cd72" "checksum array-init 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "23589ecb866b460d3a0f1278834750268c607e8e28a1b982c907219f3178cd72"
"checksum bit_field 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ed8765909f9009617974ab6b7d332625b320b33c326b1e9321382ef1999b5d56" "checksum bit_field 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ed8765909f9009617974ab6b7d332625b320b33c326b1e9321382ef1999b5d56"
"checksum bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "228047a76f468627ca71776ecdebd732a3423081fcf5125585bcd7c49886ce12" "checksum bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "228047a76f468627ca71776ecdebd732a3423081fcf5125585bcd7c49886ce12"
"checksum bootloader 0.3.12 (registry+https://github.com/rust-lang/crates.io-index)" = "2b498d7168288f3667f80aee93b4894e355dfce867803e1ccd5d9ee42a0b0e1a" "checksum bootloader 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a0808c55da932b82d3ababdaa0caa3f18522c5d2d06309b98f73adda849a3f03"
"checksum cc 1.0.30 (registry+https://github.com/rust-lang/crates.io-index)" = "d01c69d08ff207f231f07196e30f84c70f1c815b04f980f8b7b01ff01f05eb92" "checksum cc 1.0.30 (registry+https://github.com/rust-lang/crates.io-index)" = "d01c69d08ff207f231f07196e30f84c70f1c815b04f980f8b7b01ff01f05eb92"
"checksum cpuio 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "22b8e308ccfc5acf3b82f79c0eac444cf6114cb2ac67a230ca6c177210068daa" "checksum cpuio 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "22b8e308ccfc5acf3b82f79c0eac444cf6114cb2ac67a230ca6c177210068daa"
"checksum fixedvec 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7c6c16d316ccdac21a4dd648e314e76facbbaf316e83ca137d0857a9c07419d0" "checksum fixedvec 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7c6c16d316ccdac21a4dd648e314e76facbbaf316e83ca137d0857a9c07419d0"
@@ -364,6 +377,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
"checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" "checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
"checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" "checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
"checksum x86_64 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "2bd647af1614659e1febec1d681231aea4ebda4818bf55a578aff02f3e4db4b4" "checksum x86_64 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "2bd647af1614659e1febec1d681231aea4ebda4818bf55a578aff02f3e4db4b4"
"checksum x86_64 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "f9258d7e2dd25008d69e8c9e9ee37865887a5e1e3d06a62f1cb3f6c209e6f177"
"checksum x86_64 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "de155d368de1d32afc8f90838bf81986e4bd43a0cd5fcd7f7e9c85cb8f51dc7c" "checksum x86_64 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "de155d368de1d32afc8f90838bf81986e4bd43a0cd5fcd7f7e9c85cb8f51dc7c"
"checksum xmas-elf 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "22678df5df766e8d1e5d609da69f0c3132d794edf6ab5e75e7abcd2270d4cf58" "checksum xmas-elf 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "22678df5df766e8d1e5d609da69f0c3132d794edf6ab5e75e7abcd2270d4cf58"
"checksum zero 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "5f1bc8a6b2005884962297587045002d8cfb8dcec9db332f4ca216ddc5de82c5" "checksum zero 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "5f1bc8a6b2005884962297587045002d8cfb8dcec9db332f4ca216ddc5de82c5"

View File

@@ -5,7 +5,7 @@ authors = ["Philipp Oppermann <dev@phil-opp.com>"]
edition = "2018" edition = "2018"
[dependencies] [dependencies]
bootloader = "0.3.12" bootloader = { version = "0.4.0", features = ["map_physical_memory"]}
volatile = "0.2.3" volatile = "0.2.3"
spin = "0.4.9" spin = "0.4.9"
uart_16550 = "0.1.0" uart_16550 = "0.1.0"

View File

@@ -1,10 +1,10 @@
# Blog OS (Advanced Paging) # Blog OS (Paging Implementation)
[![Build Status](https://travis-ci.org/phil-opp/blog_os.svg?branch=post-10)](https://travis-ci.org/phil-opp/blog_os/branches) [![Build Status](https://travis-ci.org/phil-opp/blog_os.svg?branch=post-10)](https://travis-ci.org/phil-opp/blog_os/branches)
This repository contains the source code for the [Advanced Paging][post] post of the [Writing an OS in Rust](https://os.phil-opp.com) series. This repository contains the source code for the [Paging Implementation][post] post of the [Writing an OS in Rust](https://os.phil-opp.com) series.
[post]: https://os.phil-opp.com/advanced-paging/ [post]: https://os.phil-opp.com/paging-implementation/
**Check out the [master branch](https://github.com/phil-opp/blog_os) for more information.** **Check out the [master branch](https://github.com/phil-opp/blog_os) for more information.**

View File

@@ -3,7 +3,7 @@
#![cfg_attr(test, allow(unused_imports))] #![cfg_attr(test, allow(unused_imports))]
use blog_os::println; use blog_os::println;
use bootloader::{bootinfo::BootInfo, entry_point}; use bootloader::{entry_point, BootInfo};
use core::panic::PanicInfo; use core::panic::PanicInfo;
entry_point!(kernel_main); entry_point!(kernel_main);
@@ -11,7 +11,8 @@ entry_point!(kernel_main);
#[cfg(not(test))] #[cfg(not(test))]
fn kernel_main(boot_info: &'static BootInfo) -> ! { fn kernel_main(boot_info: &'static BootInfo) -> ! {
use blog_os::interrupts::PICS; use blog_os::interrupts::PICS;
use blog_os::memory::{self, create_example_mapping}; use blog_os::memory;
use x86_64::{structures::paging::Page, VirtAddr};
println!("Hello World{}", "!"); println!("Hello World{}", "!");
@@ -20,11 +21,16 @@ fn kernel_main(boot_info: &'static BootInfo) -> ! {
unsafe { PICS.lock().initialize() }; unsafe { PICS.lock().initialize() };
x86_64::instructions::interrupts::enable(); x86_64::instructions::interrupts::enable();
let mut recursive_page_table = unsafe { memory::init(boot_info.p4_table_addr as usize) }; let mut mapper = unsafe { memory::init(boot_info.physical_memory_offset) };
let mut frame_allocator = memory::init_frame_allocator(&boot_info.memory_map); let mut frame_allocator = memory::init_frame_allocator(&boot_info.memory_map);
create_example_mapping(&mut recursive_page_table, &mut frame_allocator); // map a previously unmapped page
unsafe { (0xdeadbeaf900 as *mut u64).write_volatile(0xf021f077f065f04e) }; let page = Page::containing_address(VirtAddr::new(0xdeadbeaf000));
memory::create_example_mapping(page, &mut mapper, &mut frame_allocator);
// write the string `New!` to the screen through the new mapping
let page_ptr: *mut u64 = page.start_address().as_mut_ptr();
unsafe { page_ptr.offset(400).write_volatile(0x_f021_f077_f065_f04e) };
println!("It did not crash!"); println!("It did not crash!");
blog_os::hlt_loop(); blog_os::hlt_loop();

View File

@@ -1,24 +1,26 @@
use bootloader::bootinfo::{MemoryMap, MemoryRegionType}; use bootloader::bootinfo::{MemoryMap, MemoryRegionType};
use x86_64::structures::paging::{ use x86_64::{
FrameAllocator, Mapper, Page, PageTable, PhysFrame, RecursivePageTable, Size4KiB, structures::paging::{
FrameAllocator, MappedPageTable, Mapper, MapperAllSizes, Page, PageTable, PhysFrame,
Size4KiB,
},
PhysAddr, VirtAddr,
}; };
use x86_64::{PhysAddr, VirtAddr};
/// Creates a RecursivePageTable instance from the level 4 address. /// Initialize a new MappedPageTable.
/// ///
/// This function is unsafe because it can break memory safety if an invalid /// This function is unsafe because the caller must guarantee that the
/// address is passed. /// complete physical memory is mapped to virtual memory at the passed
pub unsafe fn init(level_4_table_addr: usize) -> RecursivePageTable<'static> { /// `physical_memory_offset`. Also, this function must be only called once
/// Rust currently treats the whole body of unsafe functions as an unsafe /// to avoid aliasing `&mut` references (which is undefined behavior).
/// block, which makes it difficult to see which operations are unsafe. To pub unsafe fn init(physical_memory_offset: u64) -> impl MapperAllSizes {
/// limit the scope of unsafe we use a safe inner function. let level_4_table = active_level_4_table(physical_memory_offset);
fn init_inner(level_4_table_addr: usize) -> RecursivePageTable<'static> { let phys_to_virt = move |frame: PhysFrame| -> *mut PageTable {
let level_4_table_ptr = level_4_table_addr as *mut PageTable; let phys = frame.start_address().as_u64();
let level_4_table = unsafe { &mut *level_4_table_ptr }; let virt = VirtAddr::new(phys + physical_memory_offset);
RecursivePageTable::new(level_4_table).unwrap() virt.as_mut_ptr()
} };
MappedPageTable::new(level_4_table, phys_to_virt)
init_inner(level_4_table_addr)
} }
/// Create a FrameAllocator from the passed memory map /// Create a FrameAllocator from the passed memory map
@@ -39,17 +41,36 @@ pub fn init_frame_allocator(
BootInfoFrameAllocator { frames } BootInfoFrameAllocator { frames }
} }
/// Returns a mutable reference to the active level 4 table.
///
/// This function is unsafe because the caller must guarantee that the
/// complete physical memory is mapped to virtual memory at the passed
/// `physical_memory_offset`. Also, this function must be only called once
/// to avoid aliasing `&mut` references (which is undefined behavior).
unsafe fn active_level_4_table(physical_memory_offset: u64) -> &'static mut PageTable {
use x86_64::{registers::control::Cr3, VirtAddr};
let (level_4_table_frame, _) = Cr3::read();
let phys = level_4_table_frame.start_address();
let virt = VirtAddr::new(phys.as_u64() + physical_memory_offset);
let page_table_ptr: *mut PageTable = virt.as_mut_ptr();
&mut *page_table_ptr // unsafe
}
/// Creates an example mapping for the given page to frame `0xb8000`.
pub fn create_example_mapping( pub fn create_example_mapping(
recursive_page_table: &mut RecursivePageTable, page: Page,
mapper: &mut impl Mapper<Size4KiB>,
frame_allocator: &mut impl FrameAllocator<Size4KiB>, frame_allocator: &mut impl FrameAllocator<Size4KiB>,
) { ) {
use x86_64::structures::paging::PageTableFlags as Flags; use x86_64::structures::paging::PageTableFlags as Flags;
let page: Page = Page::containing_address(VirtAddr::new(0xdeadbeaf000));
let frame = PhysFrame::containing_address(PhysAddr::new(0xb8000)); let frame = PhysFrame::containing_address(PhysAddr::new(0xb8000));
let flags = Flags::PRESENT | Flags::WRITABLE; let flags = Flags::PRESENT | Flags::WRITABLE;
let map_to_result = unsafe { recursive_page_table.map_to(page, frame, flags, frame_allocator) }; let map_to_result = unsafe { mapper.map_to(page, frame, flags, frame_allocator) };
map_to_result.expect("map_to failed").flush(); map_to_result.expect("map_to failed").flush();
} }