mirror of
https://github.com/phil-opp/blog_os.git
synced 2025-12-16 14:27:49 +00:00
Merge pull request #569 from phil-opp/post-10-new
Update post-10 branch for new "Paging Implementation" post
This commit is contained in:
22
Cargo.lock
generated
22
Cargo.lock
generated
@@ -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"
|
||||||
|
|||||||
@@ -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"
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
# Blog OS (Advanced Paging)
|
# Blog OS (Paging Implementation)
|
||||||
|
|
||||||
[](https://travis-ci.org/phil-opp/blog_os/branches)
|
[](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.**
|
||||||
|
|
||||||
|
|||||||
16
src/main.rs
16
src/main.rs
@@ -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();
|
||||||
|
|||||||
@@ -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();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user