heap allocator in place, no free yet
This commit is contained in:
parent
36b51236b3
commit
3dfc440d20
10 changed files with 247 additions and 185 deletions
2
kernel-rs/Xargo.toml
Normal file
2
kernel-rs/Xargo.toml
Normal file
|
|
@ -0,0 +1,2 @@
|
||||||
|
[target.x86-bluesnow.dependencies]
|
||||||
|
alloc = {}
|
||||||
|
|
@ -3,24 +3,28 @@ extern crate core;
|
||||||
|
|
||||||
use acpi;
|
use acpi;
|
||||||
use cpuio;
|
use cpuio;
|
||||||
use context;
|
|
||||||
use memory;
|
|
||||||
use x86;
|
use x86;
|
||||||
use core::char;
|
use core::char;
|
||||||
use vga::*;
|
use vga::*;
|
||||||
|
|
||||||
fn dispatch(command: &str) -> Result <(), &'static str> {
|
fn dispatch(command: &str) -> Result <(), &'static str> {
|
||||||
match command {
|
match command {
|
||||||
"acpi" => self::acpi_info(),
|
|
||||||
"help" | "h" => self::help(),
|
"help" | "h" => self::help(),
|
||||||
"memory" => self::mb2_memory(),
|
|
||||||
"multiboot" => self::mb2_info(),
|
// multiboot
|
||||||
|
// "memory" => self::mb2_memory(),
|
||||||
|
// "multiboot" => self::mb2_info(),
|
||||||
|
// "sections" => self::mb2_sections(),
|
||||||
|
|
||||||
|
// ACPI
|
||||||
|
"acpi" => self::acpi_info(),
|
||||||
"reboot" => self::reboot(),
|
"reboot" => self::reboot(),
|
||||||
"sections" => self::mb2_sections(),
|
|
||||||
"shutdown" | "halt" | "q" => self::shutdown(),
|
"shutdown" | "halt" | "q" => self::shutdown(),
|
||||||
|
|
||||||
|
// others
|
||||||
"stack" => self::print_stack(),
|
"stack" => self::print_stack(),
|
||||||
"test" => self::test(),
|
|
||||||
"regs" => self::regs(),
|
"regs" => self::regs(),
|
||||||
|
|
||||||
_ => Err("Command unknown. (h|help for help)"),
|
_ => Err("Command unknown. (h|help for help)"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -48,12 +52,6 @@ fn help() -> Result <(), &'static str> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn test() -> Result<(), &'static str>
|
|
||||||
{
|
|
||||||
memory::test_paging(context::frame_allocator());
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Reboot the kernel
|
/// Reboot the kernel
|
||||||
///
|
///
|
||||||
/// If reboot failed, will loop on a halt cmd
|
/// If reboot failed, will loop on a halt cmd
|
||||||
|
|
@ -129,49 +127,49 @@ fn print_stack() -> Result <(), &'static str> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn mb2_memory() -> Result <(), &'static str> {
|
// fn mb2_memory() -> Result <(), &'static str> {
|
||||||
let boot_info = context::boot_info();
|
// let boot_info = context::boot_info();
|
||||||
|
|
||||||
let memory_map_tag = boot_info.memory_map_tag()
|
// let memory_map_tag = boot_info.memory_map_tag()
|
||||||
.expect("Memory map tag required");
|
// .expect("Memory map tag required");
|
||||||
|
|
||||||
println!("memory areas:");
|
// println!("memory areas:");
|
||||||
for area in memory_map_tag.memory_areas() {
|
// for area in memory_map_tag.memory_areas() {
|
||||||
println!(" start: 0x{:x}, length: 0x{:x}",
|
// println!(" start: 0x{:x}, length: 0x{:x}",
|
||||||
area.start_address(), area.size());
|
// area.start_address(), area.size());
|
||||||
}
|
// }
|
||||||
Ok(())
|
// Ok(())
|
||||||
}
|
// }
|
||||||
|
|
||||||
fn mb2_sections() -> Result <(), &'static str> {
|
// fn mb2_sections() -> Result <(), &'static str> {
|
||||||
let boot_info = context::boot_info();
|
// let boot_info = context::boot_info();
|
||||||
|
|
||||||
let elf_sections_tag = boot_info.elf_sections_tag()
|
// let elf_sections_tag = boot_info.elf_sections_tag()
|
||||||
.expect("Elf-sections tag required");
|
// .expect("Elf-sections tag required");
|
||||||
|
|
||||||
println!("kernel sections:");
|
// println!("kernel sections:");
|
||||||
for section in elf_sections_tag.sections() {
|
// for section in elf_sections_tag.sections() {
|
||||||
println!(" {: <10} {:#x}, size: {:#x}, flags: {:#X}",
|
// println!(" {: <10} {:#x}, size: {:#x}, flags: {:#X}",
|
||||||
section.name(), section.start_address(), section.size(), section.flags());
|
// section.name(), section.start_address(), section.size(), section.flags());
|
||||||
}
|
// }
|
||||||
Ok(())
|
// Ok(())
|
||||||
}
|
// }
|
||||||
|
|
||||||
fn mb2_info() -> Result <(), &'static str> {
|
// fn mb2_info() -> Result <(), &'static str> {
|
||||||
let boot_info = context::boot_info();
|
// let boot_info = context::boot_info();
|
||||||
|
|
||||||
let command_line_tag = boot_info.command_line_tag()
|
// let command_line_tag = boot_info.command_line_tag()
|
||||||
.expect("Elf-sections tag required");
|
// .expect("Elf-sections tag required");
|
||||||
|
|
||||||
let bootloader_tag = boot_info.boot_loader_name_tag()
|
// let bootloader_tag = boot_info.boot_loader_name_tag()
|
||||||
.expect("Elf-sections tag required");
|
// .expect("Elf-sections tag required");
|
||||||
|
|
||||||
println!("bootloader: {}", bootloader_tag.name());
|
// println!("bootloader: {}", bootloader_tag.name());
|
||||||
if command_line_tag.command_line().len() != 0 {
|
// if command_line_tag.command_line().len() != 0 {
|
||||||
println!("command line: {}", command_line_tag.command_line());
|
// println!("command line: {}", command_line_tag.command_line());
|
||||||
}
|
// }
|
||||||
Ok(())
|
// Ok(())
|
||||||
}
|
// }
|
||||||
|
|
||||||
pub fn acpi_info() -> Result <(), &'static str> {
|
pub fn acpi_info() -> Result <(), &'static str> {
|
||||||
acpi::info()?;
|
acpi::info()?;
|
||||||
|
|
|
||||||
|
|
@ -6,8 +6,6 @@ pub static mut CONTEXT: Option<Context> = None;
|
||||||
|
|
||||||
pub struct Context {
|
pub struct Context {
|
||||||
pub current_term: u8,
|
pub current_term: u8,
|
||||||
pub boot_info: multiboot2::BootInformation,
|
|
||||||
pub frame_allocator: memory::AreaFrameAllocator,
|
|
||||||
pub vga1: vga::Writer,
|
pub vga1: vga::Writer,
|
||||||
pub vga2: vga::Writer,
|
pub vga2: vga::Writer,
|
||||||
}
|
}
|
||||||
|
|
@ -15,94 +13,14 @@ pub struct Context {
|
||||||
impl Context
|
impl Context
|
||||||
{
|
{
|
||||||
pub fn new(multiboot_start: usize) -> Context {
|
pub fn new(multiboot_start: usize) -> Context {
|
||||||
let boot_info = unsafe { multiboot2::load(multiboot_start) };
|
|
||||||
let multiboot_end = multiboot_start + boot_info.total_size();
|
|
||||||
|
|
||||||
let elf_sections_tag = boot_info.elf_sections_tag().unwrap();
|
|
||||||
let memory_map_tag = boot_info.memory_map_tag().unwrap();
|
|
||||||
|
|
||||||
let kernel_start = elf_sections_tag.sections().map(
|
|
||||||
|s| s.start_address())
|
|
||||||
.min().unwrap() as usize;
|
|
||||||
let kernel_end = elf_sections_tag.sections().map(
|
|
||||||
|s| s.start_address() + s.size())
|
|
||||||
.max().unwrap() as usize;
|
|
||||||
|
|
||||||
let frame_allocator = memory::AreaFrameAllocator::new(
|
|
||||||
kernel_start, kernel_end, multiboot_start,
|
|
||||||
multiboot_end, memory_map_tag.memory_areas());
|
|
||||||
|
|
||||||
let vga1 = vga::Writer::new();
|
|
||||||
let vga2 = vga::Writer::new();
|
|
||||||
|
|
||||||
Context {
|
Context {
|
||||||
current_term: 0,
|
current_term: 0,
|
||||||
boot_info,
|
boot_info,
|
||||||
frame_allocator,
|
|
||||||
vga1,
|
vga1,
|
||||||
vga2,
|
vga2,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn init_screen() {
|
|
||||||
set_color!(White, Cyan);
|
|
||||||
print!("{}{}{}{}{}{}{}{}{}{}{}{}{}{}",
|
|
||||||
format_args!("{: ^80}", r#" ,--, "#),
|
|
||||||
format_args!("{: ^80}", r#" ,--.'| ,----, "#),
|
|
||||||
format_args!("{: ^80}", r#" ,--, | : .' .' \ "#),
|
|
||||||
format_args!("{: ^80}", r#",---.'| : ' ,----,' | "#),
|
|
||||||
format_args!("{: ^80}", r#"; : | | ; | : . ; "#),
|
|
||||||
format_args!("{: ^80}", r#"| | : _' | ; |.' / "#),
|
|
||||||
format_args!("{: ^80}", r#": : |.' | `----'/ ; "#),
|
|
||||||
format_args!("{: ^80}", r#"| ' ' ; : / ; / "#),
|
|
||||||
format_args!("{: ^80}", r#"\ \ .'. | ; / /-, "#),
|
|
||||||
format_args!("{: ^80}", r#" `---`: | ' / / /.`| "#),
|
|
||||||
format_args!("{: ^80}", r#" ' ; |./__; : "#),
|
|
||||||
format_args!("{: ^80}", r#" | : ;| : .' "#),
|
|
||||||
format_args!("{: ^80}", r#" ' ,/ ; | .' "#),
|
|
||||||
format_args!("{: ^80}", r#" '--' `---' "#));
|
|
||||||
set_color!();
|
|
||||||
context().vga1.prompt();
|
|
||||||
context().vga2.prompt();
|
|
||||||
context().vga1.flush();
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn frame_allocator() -> &'static mut memory::AreaFrameAllocator {
|
|
||||||
&mut context().frame_allocator
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn boot_info() -> &'static multiboot2::BootInformation {
|
|
||||||
&context().boot_info
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn switch_term() {
|
|
||||||
context().current_term = {
|
|
||||||
if context().current_term == 0 { 1 }
|
|
||||||
else { 0 }
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn current_term() -> &'static mut vga::Writer{
|
|
||||||
if context().current_term == 0 {
|
|
||||||
&mut context().vga1
|
|
||||||
} else {
|
|
||||||
&mut context().vga2
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn context() -> &'static mut Context {
|
|
||||||
unsafe {
|
|
||||||
match CONTEXT {
|
|
||||||
Some(ref mut x) => &mut *x,
|
|
||||||
None => panic!(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn init(multiboot_info_addr: usize) {
|
|
||||||
unsafe { CONTEXT = Some(Context::new(multiboot_info_addr)) };
|
|
||||||
|
|
||||||
memory::remap_the_kernel(frame_allocator(), boot_info());
|
|
||||||
self::init_screen();
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
extern crate core;
|
extern crate core;
|
||||||
|
|
||||||
use cpuio;
|
use cpuio;
|
||||||
use context;
|
use vga;
|
||||||
|
|
||||||
const MAX_KEYS: usize = 59;
|
const MAX_KEYS: usize = 59;
|
||||||
const KEYMAP_US: [[u8;2]; MAX_KEYS] = [
|
const KEYMAP_US: [[u8;2]; MAX_KEYS] = [
|
||||||
|
|
@ -91,19 +91,20 @@ pub fn kbd_callback() {
|
||||||
0x2A | 0x36 => {SHIFT = !is_release},
|
0x2A | 0x36 => {SHIFT = !is_release},
|
||||||
0x38 => {ALT = !is_release},
|
0x38 => {ALT = !is_release},
|
||||||
0x1D => {CTRL = !is_release},
|
0x1D => {CTRL = !is_release},
|
||||||
0x0F if !is_release => {
|
// terminal switching
|
||||||
context::switch_term();
|
// 0x0F if !is_release => {
|
||||||
context::current_term().flush();
|
// context::switch_term();
|
||||||
},
|
// context::current_term().flush();
|
||||||
|
// },
|
||||||
0x0E if !is_release => {
|
0x0E if !is_release => {
|
||||||
context::current_term().backspace();
|
vga::VGA.backspace();
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
Some(ascii) if !is_release => {
|
Some(ascii) if !is_release => {
|
||||||
let sym = if SHIFT { ascii[1] } else { ascii[0] };
|
let sym = if SHIFT { ascii[1] } else { ascii[0] };
|
||||||
context::current_term().keypress(sym);
|
vga::VGA.keypress(sym);
|
||||||
},
|
},
|
||||||
Some(_) => {},
|
Some(_) => {},
|
||||||
None =>{},
|
None =>{},
|
||||||
|
|
|
||||||
|
|
@ -5,15 +5,17 @@
|
||||||
#![feature(const_fn)]
|
#![feature(const_fn)]
|
||||||
#![feature(ptr_internals)]
|
#![feature(ptr_internals)]
|
||||||
#![feature(asm)]
|
#![feature(asm)]
|
||||||
|
#![feature(alloc)]
|
||||||
|
#![feature(allocator_api)]
|
||||||
|
#![feature(global_allocator)]
|
||||||
|
|
||||||
extern crate rlibc;
|
extern crate rlibc;
|
||||||
extern crate multiboot2; //slightly modified fork from official 0.3.2
|
extern crate multiboot2;
|
||||||
#[macro_use] extern crate bitflags;
|
#[macro_use] extern crate bitflags;
|
||||||
|
#[macro_use] extern crate alloc;
|
||||||
|
|
||||||
/// 80x25 screen and simplistic terminal driver
|
/// 80x25 screen and simplistic terminal driver
|
||||||
#[macro_use] pub mod vga;
|
#[macro_use] pub mod vga;
|
||||||
/// kernel init and environment
|
|
||||||
pub mod context;
|
|
||||||
/// PS/2 detection and processing
|
/// PS/2 detection and processing
|
||||||
pub mod keyboard;
|
pub mod keyboard;
|
||||||
/// simplisitc kernel commands
|
/// simplisitc kernel commands
|
||||||
|
|
@ -24,17 +26,37 @@ pub mod cpuio;
|
||||||
pub mod acpi;
|
pub mod acpi;
|
||||||
/// physical frame allocator + paging module
|
/// physical frame allocator + paging module
|
||||||
pub mod memory;
|
pub mod memory;
|
||||||
/// a few x86 instruction wrappers
|
/// a few x86 register and instruction wrappers
|
||||||
pub mod x86;
|
pub mod x86;
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub extern fn kmain(multiboot_info_addr: usize) -> ! {
|
pub extern fn kmain(multiboot_info_addr: usize) -> ! {
|
||||||
context::init(multiboot_info_addr);
|
|
||||||
// println!("init done!");
|
|
||||||
// acpi::init().unwrap();
|
// acpi::init().unwrap();
|
||||||
|
let boot_info = unsafe { multiboot2::load(multiboot_info_addr) };
|
||||||
|
enable_write_protect_bit();
|
||||||
|
|
||||||
|
vga::init();
|
||||||
|
memory::init(&boot_info);
|
||||||
|
|
||||||
|
use alloc::boxed::Box;
|
||||||
|
let mut heap_test = Box::new(42);
|
||||||
|
*heap_test -= 15;
|
||||||
|
let heap_test2 = Box::new("Hello");
|
||||||
|
println!("{:?} {:?}", heap_test, heap_test2);
|
||||||
|
|
||||||
|
let mut vec_test = vec![1,2,3,4,5,6,7];
|
||||||
|
vec_test[3] = 42;
|
||||||
|
for i in &vec_test {
|
||||||
|
print!("{} ", i);
|
||||||
|
}
|
||||||
|
|
||||||
loop { keyboard::kbd_callback(); }
|
loop { keyboard::kbd_callback(); }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn enable_write_protect_bit() {
|
||||||
|
unsafe { x86::cr0_write(x86::cr0() | (1 << 16)) };
|
||||||
|
}
|
||||||
|
|
||||||
#[lang = "eh_personality"] #[no_mangle]
|
#[lang = "eh_personality"] #[no_mangle]
|
||||||
pub extern fn eh_personality() {
|
pub extern fn eh_personality() {
|
||||||
|
|
||||||
|
|
@ -51,3 +73,11 @@ pub extern fn panic_fmt(fmt: core::fmt::Arguments, file: &'static str, line: u32
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
use memory::BumpAllocator;
|
||||||
|
|
||||||
|
pub const HEAP_START: usize = (1 << 22); //first entry of p2
|
||||||
|
pub const HEAP_SIZE: usize = 100 * 1024; //100 KiB
|
||||||
|
|
||||||
|
#[global_allocator]
|
||||||
|
static HEAP_ALLOCATOR: BumpAllocator = BumpAllocator::new(HEAP_START,
|
||||||
|
HEAP_START + HEAP_SIZE);
|
||||||
|
|
|
||||||
60
kernel-rs/src/memory/heap_allocator.rs
Normal file
60
kernel-rs/src/memory/heap_allocator.rs
Normal file
|
|
@ -0,0 +1,60 @@
|
||||||
|
use alloc::heap::{Alloc, AllocErr, Layout};
|
||||||
|
use core::sync::atomic::{AtomicUsize, Ordering};
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct BumpAllocator {
|
||||||
|
heap_start: usize,
|
||||||
|
heap_end: usize,
|
||||||
|
next: AtomicUsize,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl BumpAllocator {
|
||||||
|
pub const fn new(heap_start: usize, heap_end: usize) -> Self {
|
||||||
|
Self { heap_start, heap_end, next: AtomicUsize::new(heap_start) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe impl<'a> Alloc for &'a BumpAllocator {
|
||||||
|
unsafe fn alloc(&mut self, layout: Layout) -> Result<*mut u8, AllocErr> {
|
||||||
|
loop {
|
||||||
|
// load current state of the `next` field
|
||||||
|
let current_next = self.next.load(Ordering::Relaxed);
|
||||||
|
let alloc_start = align_up(current_next, layout.align());
|
||||||
|
let alloc_end = alloc_start.saturating_add(layout.size());
|
||||||
|
|
||||||
|
if alloc_end <= self.heap_end {
|
||||||
|
// update the `next` pointer if it still has the value `current_next`
|
||||||
|
let next_now = self.next.compare_and_swap(current_next, alloc_end,
|
||||||
|
Ordering::Relaxed);
|
||||||
|
if next_now == current_next {
|
||||||
|
return Ok(alloc_start as *mut u8);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return Err(AllocErr::Exhausted{ request: layout })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe fn dealloc(&mut self, pt: *mut u8, layout: Layout) {
|
||||||
|
// TODO
|
||||||
|
// do nothing, leak memory
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Align downwards. Returns the greatest x with alignment `align`
|
||||||
|
/// so that x <= addr. The alignment must be a power of 2.
|
||||||
|
pub fn align_down(addr: usize, align: usize) -> usize {
|
||||||
|
if align.is_power_of_two() {
|
||||||
|
addr & !(align - 1)
|
||||||
|
} else if align == 0 {
|
||||||
|
addr
|
||||||
|
} else {
|
||||||
|
panic!("`align` must be a power of 2");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Align upwards. Returns the smallest x with alignment `align`
|
||||||
|
/// so that x >= addr. The alignment must be a power of 2.
|
||||||
|
pub fn align_up(addr: usize, align: usize) -> usize {
|
||||||
|
align_down(addr + align - 1, align)
|
||||||
|
}
|
||||||
|
|
@ -1,12 +1,14 @@
|
||||||
pub const PAGE_SIZE: usize = 4096;
|
pub const PAGE_SIZE: usize = 4096;
|
||||||
|
|
||||||
mod area_allocator;
|
mod area_allocator;
|
||||||
|
mod heap_allocator;
|
||||||
mod paging;
|
mod paging;
|
||||||
|
|
||||||
pub use self::area_allocator::*;
|
pub use self::area_allocator::*;
|
||||||
pub use self::paging::test_paging;
|
pub use self::heap_allocator::*;
|
||||||
pub use self::paging::remap_the_kernel;
|
pub use self::paging::remap_the_kernel;
|
||||||
use self::paging::PhysicalAddress;
|
use self::paging::PhysicalAddress;
|
||||||
|
use multiboot2;
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord)]
|
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord)]
|
||||||
pub struct Frame {
|
pub struct Frame {
|
||||||
|
|
@ -57,3 +59,36 @@ impl Iterator for FrameIter {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// memory initialisation should only be called once
|
||||||
|
pub fn init(boot_info: &multiboot2::BootInformation) {
|
||||||
|
let elf_sections_tag = boot_info.elf_sections_tag().unwrap();
|
||||||
|
let memory_map_tag = boot_info.memory_map_tag().unwrap();
|
||||||
|
|
||||||
|
let kernel_start = elf_sections_tag.sections()
|
||||||
|
.filter(|s| s.is_allocated())
|
||||||
|
.map(|s| s.start_address())
|
||||||
|
.min().unwrap();
|
||||||
|
|
||||||
|
let kernel_end = elf_sections_tag.sections()
|
||||||
|
.filter(|s| s.is_allocated())
|
||||||
|
.map(|s| s.start_address() + s.size())
|
||||||
|
.max().unwrap();
|
||||||
|
|
||||||
|
let mut frame_allocator = self::AreaFrameAllocator::new(
|
||||||
|
kernel_start as usize, kernel_end as usize,
|
||||||
|
boot_info.start_address(), boot_info.start_address(),
|
||||||
|
memory_map_tag.memory_areas());
|
||||||
|
|
||||||
|
let mut active_table = paging::remap_the_kernel(&mut frame_allocator,
|
||||||
|
boot_info);
|
||||||
|
use self::paging::Page;
|
||||||
|
use {HEAP_START, HEAP_SIZE};
|
||||||
|
|
||||||
|
let heap_start_page = Page::containing_address(HEAP_START);
|
||||||
|
let heap_end_page = Page::containing_address(HEAP_START + HEAP_SIZE - 1);
|
||||||
|
|
||||||
|
for page in Page::range_inclusive(heap_start_page, heap_end_page) {
|
||||||
|
active_table.map(page, paging::EntryFlags::WRITABLE, &mut frame_allocator);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,7 @@ const ENTRY_COUNT: usize = 1024;
|
||||||
pub type PhysicalAddress = usize;
|
pub type PhysicalAddress = usize;
|
||||||
pub type VirtualAddress = usize;
|
pub type VirtualAddress = usize;
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
|
||||||
pub struct Page {
|
pub struct Page {
|
||||||
number: usize,
|
number: usize,
|
||||||
}
|
}
|
||||||
|
|
@ -46,6 +46,33 @@ impl Page {
|
||||||
fn p1_index(&self) -> usize {
|
fn p1_index(&self) -> usize {
|
||||||
(self.number >> 0) & 0x3ff
|
(self.number >> 0) & 0x3ff
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn range_inclusive(start: Page, end: Page) -> PageIter {
|
||||||
|
PageIter {
|
||||||
|
start,
|
||||||
|
end,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct PageIter {
|
||||||
|
start: Page,
|
||||||
|
end: Page,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Iterator for PageIter {
|
||||||
|
type Item = Page;
|
||||||
|
|
||||||
|
fn next(&mut self) -> Option<Page> {
|
||||||
|
if self.start <= self.end {
|
||||||
|
let page = self.start;
|
||||||
|
self.start.number += 1;
|
||||||
|
Some(page)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct ActivePageTable {
|
pub struct ActivePageTable {
|
||||||
|
|
@ -99,14 +126,12 @@ impl ActivePageTable {
|
||||||
|
|
||||||
let p2_frame = Frame::containing_address(x86::cr3() as usize);
|
let p2_frame = Frame::containing_address(x86::cr3() as usize);
|
||||||
|
|
||||||
println!("old p2_frame at {}", p2_frame.number);
|
|
||||||
let old_table = InactivePageTable {
|
let old_table = InactivePageTable {
|
||||||
p2_frame,
|
p2_frame,
|
||||||
};
|
};
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
let frame = Frame::containing_address(new_table.p2_frame.start_address());
|
let frame = Frame::containing_address(new_table.p2_frame.start_address());
|
||||||
println!("new p2_frame at {:#x}", new_table.p2_frame.start_address());
|
|
||||||
x86::cr3_write(frame.start_address());
|
x86::cr3_write(frame.start_address());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -166,9 +191,6 @@ pub fn remap_the_kernel<A>(allocator: &mut A, boot_info: &BootInformation)
|
||||||
assert!(section.start_address() % PAGE_SIZE as u64 == 0,
|
assert!(section.start_address() % PAGE_SIZE as u64 == 0,
|
||||||
"sections need to be page aligned");
|
"sections need to be page aligned");
|
||||||
|
|
||||||
println!("mapping section at addr: {:#x}, size: {:#x}",
|
|
||||||
section.start_address(), section.size());
|
|
||||||
|
|
||||||
let flags = EntryFlags::from_elf_section_flags(§ion);
|
let flags = EntryFlags::from_elf_section_flags(§ion);
|
||||||
let start_frame = Frame::containing_address(section.start_address() as usize);
|
let start_frame = Frame::containing_address(section.start_address() as usize);
|
||||||
let end_frame = Frame::containing_address(section.end_address() as usize - 1);
|
let end_frame = Frame::containing_address(section.end_address() as usize - 1);
|
||||||
|
|
@ -192,31 +214,5 @@ pub fn remap_the_kernel<A>(allocator: &mut A, boot_info: &BootInformation)
|
||||||
|
|
||||||
active_table.unmap(old_p2_page, allocator);
|
active_table.unmap(old_p2_page, allocator);
|
||||||
|
|
||||||
println!("guard page at {:#x}", old_p2_page.start_address());
|
|
||||||
println!("cr3 = {:#x}", x86::cr3());
|
|
||||||
|
|
||||||
active_table
|
active_table
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn test_paging<A>(allocator: &mut A)
|
|
||||||
where A: FrameAllocator
|
|
||||||
{
|
|
||||||
let mut page_table = unsafe { ActivePageTable::new() };
|
|
||||||
|
|
||||||
let addr = 0xffff_f000;
|
|
||||||
let page = Page::containing_address(addr);
|
|
||||||
let frame = allocator.allocate_frame().expect("no more frames");
|
|
||||||
println!("None = {:?}, map to {:?}",
|
|
||||||
page_table.translate(addr),
|
|
||||||
frame);
|
|
||||||
println!("check 0");
|
|
||||||
flush!();
|
|
||||||
page_table.map_to(page, frame, EntryFlags::empty(), allocator);
|
|
||||||
println!("check 1");
|
|
||||||
flush!();
|
|
||||||
println!("Some = {:?}", page_table.translate(addr));
|
|
||||||
flush!();
|
|
||||||
println!("next free frame: {:?}", allocator.allocate_frame());
|
|
||||||
flush!();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -51,7 +51,6 @@ impl<L> Table<L> where L: HierarchicalLevel
|
||||||
where A: FrameAllocator
|
where A: FrameAllocator
|
||||||
{
|
{
|
||||||
if self.next_table(index).is_none() {
|
if self.next_table(index).is_none() {
|
||||||
println!("index={} flags={:#b}", index, self[index].flags());
|
|
||||||
assert!(!self[index].flags().contains(EntryFlags::HUGE_PAGE),
|
assert!(!self[index].flags().contains(EntryFlags::HUGE_PAGE),
|
||||||
"mapping code does not support huge pages");
|
"mapping code does not support huge pages");
|
||||||
let frame = allocator.allocate_frame().expect("no frames available");
|
let frame = allocator.allocate_frame().expect("no frames available");
|
||||||
|
|
|
||||||
|
|
@ -2,10 +2,11 @@ pub mod color;
|
||||||
|
|
||||||
pub use self::color::{Color, ColorCode};
|
pub use self::color::{Color, ColorCode};
|
||||||
|
|
||||||
use context;
|
|
||||||
use cpuio;
|
use cpuio;
|
||||||
use console;
|
use console;
|
||||||
|
|
||||||
|
pub static mut VGA: Writer = self::Writer::new();
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy)]
|
#[derive(Debug, Clone, Copy)]
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
struct ScreenChar {
|
struct ScreenChar {
|
||||||
|
|
@ -25,21 +26,21 @@ macro_rules! println {
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! flush {
|
macro_rules! flush {
|
||||||
() => ($crate::context::current_term().flush());
|
() => (unsafe { $crate::vga::VGA.flush() });
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! set_color {
|
macro_rules! set_color {
|
||||||
() => ($crate::context::current_term().color_code =
|
() => (unsafe { $crate::vga::VGA.color_code =
|
||||||
$crate::vga::ColorCode::new($crate::vga::Color::White, $crate::vga::Color::Black));
|
$crate::vga::ColorCode::new($crate::vga::Color::White, $crate::vga::Color::Black)} );
|
||||||
($fg:ident) => ($crate::context::current_term().color_code =
|
($fg:ident) => (unsafe { $crate::vga::VGA.color_code =
|
||||||
$crate::vga::ColorCode::new($crate::vga::Color::$fg, $crate::vga::Color::Black));
|
$crate::vga::ColorCode::new($crate::vga::Color::$fg, $crate::vga::Color::Black)} );
|
||||||
($fg:ident, $bg:ident) => ($crate::context::current_term().color_code =
|
($fg:ident, $bg:ident) => (unsafe { $crate::vga::VGA.color_code =
|
||||||
$crate::vga::ColorCode::new($crate::vga::Color::$fg, $crate::vga::Color::$bg));
|
$crate::vga::ColorCode::new($crate::vga::Color::$fg, $crate::vga::Color::$bg)} );
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn print(args: fmt::Arguments) {
|
pub fn print(args: fmt::Arguments) {
|
||||||
use core::fmt::Write;
|
use core::fmt::Write;
|
||||||
context::current_term().write_fmt(args).unwrap();
|
unsafe { self::VGA.write_fmt(args).unwrap(); }
|
||||||
}
|
}
|
||||||
|
|
||||||
extern crate core;
|
extern crate core;
|
||||||
|
|
@ -195,3 +196,25 @@ impl fmt::Write for Writer {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn init() {
|
||||||
|
set_color!(White, Cyan);
|
||||||
|
print!("{}{}{}{}{}{}{}{}{}{}{}{}{}{}",
|
||||||
|
format_args!("{: ^80}", r#" ,--, "#),
|
||||||
|
format_args!("{: ^80}", r#" ,--.'| ,----, "#),
|
||||||
|
format_args!("{: ^80}", r#" ,--, | : .' .' \ "#),
|
||||||
|
format_args!("{: ^80}", r#",---.'| : ' ,----,' | "#),
|
||||||
|
format_args!("{: ^80}", r#"; : | | ; | : . ; "#),
|
||||||
|
format_args!("{: ^80}", r#"| | : _' | ; |.' / "#),
|
||||||
|
format_args!("{: ^80}", r#": : |.' | `----'/ ; "#),
|
||||||
|
format_args!("{: ^80}", r#"| ' ' ; : / ; / "#),
|
||||||
|
format_args!("{: ^80}", r#"\ \ .'. | ; / /-, "#),
|
||||||
|
format_args!("{: ^80}", r#" `---`: | ' / / /.`| "#),
|
||||||
|
format_args!("{: ^80}", r#" ' ; |./__; : "#),
|
||||||
|
format_args!("{: ^80}", r#" | : ;| : .' "#),
|
||||||
|
format_args!("{: ^80}", r#" ' ,/ ; | .' "#),
|
||||||
|
format_args!("{: ^80}", r#" '--' `---' "#));
|
||||||
|
set_color!();
|
||||||
|
unsafe { VGA.prompt(); }
|
||||||
|
unsafe { VGA.flush(); }
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue