heap allocations
This commit is contained in:
parent
c8b71f2294
commit
ec9264620b
@ -1,6 +1,6 @@
|
|||||||
[unstable]
|
[unstable]
|
||||||
build-std-features = ["compiler-builtins-mem"]
|
build-std-features = ["compiler-builtins-mem"]
|
||||||
build-std = ["core", "compiler_builtins"]
|
build-std = ["core", "compiler_builtins", "alloc"]
|
||||||
|
|
||||||
[build]
|
[build]
|
||||||
target = "x86_64-rust_os.json"
|
target = "x86_64-rust_os.json"
|
||||||
|
|||||||
41
Cargo.lock
generated
41
Cargo.lock
generated
@ -29,6 +29,30 @@ dependencies = [
|
|||||||
"spin",
|
"spin",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "linked_list_allocator"
|
||||||
|
version = "0.9.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d0b725207570aa16096962d0b20c79f8a543df2280bd3c903022b9b0b4d7ea68"
|
||||||
|
dependencies = [
|
||||||
|
"spinning_top",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "lock_api"
|
||||||
|
version = "0.4.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0382880606dff6d15c9476c416d18690b72742aa7b605bb6dd6ec9030fbf07eb"
|
||||||
|
dependencies = [
|
||||||
|
"scopeguard",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pc-keyboard"
|
||||||
|
version = "0.5.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5c6f2d937e3b8d63449b01401e2bae4041bc9dd1129c2e3e0d239407cf6635ac"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pic8259"
|
name = "pic8259"
|
||||||
version = "0.10.1"
|
version = "0.10.1"
|
||||||
@ -44,6 +68,8 @@ version = "0.1.0"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"bootloader",
|
"bootloader",
|
||||||
"lazy_static",
|
"lazy_static",
|
||||||
|
"linked_list_allocator",
|
||||||
|
"pc-keyboard",
|
||||||
"pic8259",
|
"pic8259",
|
||||||
"spin",
|
"spin",
|
||||||
"uart_16550",
|
"uart_16550",
|
||||||
@ -51,12 +77,27 @@ dependencies = [
|
|||||||
"x86_64",
|
"x86_64",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "scopeguard"
|
||||||
|
version = "1.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "spin"
|
name = "spin"
|
||||||
version = "0.5.2"
|
version = "0.5.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d"
|
checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "spinning_top"
|
||||||
|
version = "0.2.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "75adad84ee84b521fb2cca2d4fd0f1dab1d8d026bda3c5bea4ca63b5f9f9293c"
|
||||||
|
dependencies = [
|
||||||
|
"lock_api",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "uart_16550"
|
name = "uart_16550"
|
||||||
version = "0.2.15"
|
version = "0.2.15"
|
||||||
|
|||||||
@ -4,13 +4,14 @@ version = "0.1.0"
|
|||||||
edition = "2018"
|
edition = "2018"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
bootloader = "0.9.8"
|
bootloader = { version = "0.9.8", features = ["map_physical_memory"]}
|
||||||
volatile = "0.2.6"
|
volatile = "0.2.6"
|
||||||
spin = "0.5.2"
|
spin = "0.5.2"
|
||||||
x86_64 = "0.14.2"
|
x86_64 = "0.14.2"
|
||||||
uart_16550 = "0.2.0"
|
uart_16550 = "0.2.0"
|
||||||
pic8259 = "0.10.1"
|
pic8259 = "0.10.1"
|
||||||
pc-keyboard = "0.5.0"
|
pc-keyboard = "0.5.0"
|
||||||
|
linked_list_allocator = "0.9.0"
|
||||||
|
|
||||||
[dependencies.lazy_static]
|
[dependencies.lazy_static]
|
||||||
version = "1.0"
|
version = "1.0"
|
||||||
|
|||||||
@ -1,9 +1,17 @@
|
|||||||
use x86_64::structures::idt::{InterruptDescriptorTable, InterruptStackFrame};
|
use x86_64::structures::idt::{PageFaultErrorCode, InterruptDescriptorTable, InterruptStackFrame};
|
||||||
use crate::println;
|
use pic8259::ChainedPics;
|
||||||
use crate::print;
|
|
||||||
|
|
||||||
use lazy_static::lazy_static;
|
use lazy_static::lazy_static;
|
||||||
|
|
||||||
|
use crate::println;
|
||||||
|
use crate::print;
|
||||||
use crate::gdt;
|
use crate::gdt;
|
||||||
|
use crate::hlt_loop;
|
||||||
|
|
||||||
|
use spin;
|
||||||
|
|
||||||
|
pub const PIC_1_OFFSET: u8 = 32;
|
||||||
|
pub const PIC_2_OFFSET: u8 = PIC_1_OFFSET + 8;
|
||||||
|
|
||||||
lazy_static! {
|
lazy_static! {
|
||||||
static ref IDT: InterruptDescriptorTable = {
|
static ref IDT: InterruptDescriptorTable = {
|
||||||
@ -17,9 +25,23 @@ lazy_static! {
|
|||||||
.set_handler_fn(timer_interrupt_handler);
|
.set_handler_fn(timer_interrupt_handler);
|
||||||
idt[InterruptIndex::Keyboard.as_usize()]
|
idt[InterruptIndex::Keyboard.as_usize()]
|
||||||
.set_handler_fn(keyboard_interrupt_handler);
|
.set_handler_fn(keyboard_interrupt_handler);
|
||||||
|
idt.page_fault.set_handler_fn(page_fault_handler);
|
||||||
idt
|
idt
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extern "x86-interrupt" fn page_fault_handler(
|
||||||
|
stack_frame: InterruptStackFrame,
|
||||||
|
error_code: PageFaultErrorCode,
|
||||||
|
) {
|
||||||
|
use x86_64::registers::control::Cr2;
|
||||||
|
|
||||||
|
println!("EXCEPTION: PAGE FAULT");
|
||||||
|
println!("Accessed Address: {:?}", Cr2::read());
|
||||||
|
println!("Error Code: {:?}", error_code);
|
||||||
|
println!("{:#?}", stack_frame);
|
||||||
|
hlt_loop();
|
||||||
|
}
|
||||||
|
|
||||||
extern "x86-interrupt" fn double_fault_handler(
|
extern "x86-interrupt" fn double_fault_handler(
|
||||||
stack_frame: InterruptStackFrame, _error_code: u64) -> !
|
stack_frame: InterruptStackFrame, _error_code: u64) -> !
|
||||||
@ -37,6 +59,12 @@ extern "x86-interrupt" fn timer_interrupt_handler(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extern "x86-interrupt" fn breakpoint_handler(
|
||||||
|
stack_frame: InterruptStackFrame)
|
||||||
|
{
|
||||||
|
println!("EXCEPTION: BREAKPOINT\n{:#?}", stack_frame);
|
||||||
|
}
|
||||||
|
|
||||||
extern "x86-interrupt" fn keyboard_interrupt_handler(
|
extern "x86-interrupt" fn keyboard_interrupt_handler(
|
||||||
_stack_frame: InterruptStackFrame)
|
_stack_frame: InterruptStackFrame)
|
||||||
{
|
{
|
||||||
@ -75,23 +103,6 @@ pub fn init_idt() {
|
|||||||
IDT.load();
|
IDT.load();
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test_case]
|
|
||||||
fn test_breakpoint_exception() {
|
|
||||||
x86_64::instructions::interrupts::int3();
|
|
||||||
}
|
|
||||||
|
|
||||||
extern "x86-interrupt" fn breakpoint_handler(
|
|
||||||
stack_frame: InterruptStackFrame)
|
|
||||||
{
|
|
||||||
println!("EXCEPTION: BREAKPOINT\n{:#?}", stack_frame);
|
|
||||||
}
|
|
||||||
|
|
||||||
use pic8259::ChainedPics;
|
|
||||||
use spin;
|
|
||||||
|
|
||||||
pub const PIC_1_OFFSET: u8 = 32;
|
|
||||||
pub const PIC_2_OFFSET: u8 = PIC_1_OFFSET + 8;
|
|
||||||
|
|
||||||
pub static PICS: spin::Mutex<ChainedPics> =
|
pub static PICS: spin::Mutex<ChainedPics> =
|
||||||
spin::Mutex::new(unsafe { ChainedPics::new(PIC_1_OFFSET, PIC_2_OFFSET) });
|
spin::Mutex::new(unsafe { ChainedPics::new(PIC_1_OFFSET, PIC_2_OFFSET) });
|
||||||
|
|
||||||
@ -110,4 +121,9 @@ impl InterruptIndex {
|
|||||||
fn as_usize(self) -> usize {
|
fn as_usize(self) -> usize {
|
||||||
usize::from(self.as_u8())
|
usize::from(self.as_u8())
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test_case]
|
||||||
|
fn test_breakpoint_exception() {
|
||||||
|
x86_64::instructions::interrupts::int3();
|
||||||
}
|
}
|
||||||
21
src/lib.rs
21
src/lib.rs
@ -1,6 +1,7 @@
|
|||||||
#![no_std]
|
#![no_std]
|
||||||
#![cfg_attr(test, no_main)]
|
#![cfg_attr(test, no_main)]
|
||||||
#![feature(custom_test_frameworks)]
|
#![feature(custom_test_frameworks)]
|
||||||
|
#![feature(alloc_error_handler)]
|
||||||
#![test_runner(crate::test_runner)]
|
#![test_runner(crate::test_runner)]
|
||||||
#![reexport_test_harness_main = "test_main"]
|
#![reexport_test_harness_main = "test_main"]
|
||||||
#![feature(abi_x86_interrupt)]
|
#![feature(abi_x86_interrupt)]
|
||||||
@ -11,6 +12,16 @@ pub mod serial;
|
|||||||
pub mod vga_buffer;
|
pub mod vga_buffer;
|
||||||
pub mod interrupts;
|
pub mod interrupts;
|
||||||
pub mod gdt;
|
pub mod gdt;
|
||||||
|
pub mod memory;
|
||||||
|
pub mod allocator;
|
||||||
|
|
||||||
|
extern crate alloc;
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
use bootloader::{entry_point, BootInfo};
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
entry_point!(test_kernel_main);
|
||||||
|
|
||||||
pub trait Testable {
|
pub trait Testable {
|
||||||
fn run(&self) -> ();
|
fn run(&self) -> ();
|
||||||
@ -50,9 +61,8 @@ pub fn init() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
#[no_mangle]
|
fn test_kernel_main(_boot_info: &'static BootInfo) -> ! {
|
||||||
pub extern "C" fn _start() -> ! {
|
init();
|
||||||
init(); // new
|
|
||||||
test_main();
|
test_main();
|
||||||
hlt_loop();
|
hlt_loop();
|
||||||
}
|
}
|
||||||
@ -63,6 +73,11 @@ fn panic(info: &PanicInfo) -> ! {
|
|||||||
test_panic_handler(info)
|
test_panic_handler(info)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[alloc_error_handler]
|
||||||
|
fn alloc_error_handler(layout: alloc::alloc::Layout) -> ! {
|
||||||
|
panic!("allocation error: {:?}", layout)
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||||
#[repr(u32)]
|
#[repr(u32)]
|
||||||
pub enum QemuExitCode {
|
pub enum QemuExitCode {
|
||||||
|
|||||||
43
src/main.rs
43
src/main.rs
@ -4,16 +4,50 @@
|
|||||||
#![test_runner(rust_os::test_runner)]
|
#![test_runner(rust_os::test_runner)]
|
||||||
#![reexport_test_harness_main = "test_main"]
|
#![reexport_test_harness_main = "test_main"]
|
||||||
|
|
||||||
|
extern crate alloc;
|
||||||
|
|
||||||
|
use alloc::{boxed::Box, vec, vec::Vec, rc::Rc};
|
||||||
use core::panic::PanicInfo;
|
use core::panic::PanicInfo;
|
||||||
use rust_os::println;
|
use rust_os::println;
|
||||||
|
use bootloader::{BootInfo, entry_point};
|
||||||
|
use x86_64::VirtAddr;
|
||||||
|
|
||||||
|
entry_point!(kernel_main);
|
||||||
|
|
||||||
|
fn kernel_main(boot_info: &'static BootInfo) -> ! {
|
||||||
|
use rust_os::allocator;
|
||||||
|
use rust_os::memory::{self, BootInfoFrameAllocator};
|
||||||
|
|
||||||
#[no_mangle]
|
|
||||||
pub extern "C" fn _start() -> ! {
|
|
||||||
println!("Hello World{}", "!");
|
println!("Hello World{}", "!");
|
||||||
|
|
||||||
rust_os::init();
|
rust_os::init();
|
||||||
|
|
||||||
// as before
|
let phys_mem_offset = VirtAddr::new(boot_info.physical_memory_offset);
|
||||||
|
let mut mapper = unsafe { memory::init(phys_mem_offset) };
|
||||||
|
let mut frame_allocator = unsafe {
|
||||||
|
BootInfoFrameAllocator::init(&boot_info.memory_map)
|
||||||
|
};
|
||||||
|
|
||||||
|
allocator::init_heap(&mut mapper, &mut frame_allocator)
|
||||||
|
.expect("heap initialization failed");
|
||||||
|
|
||||||
|
// allocate a number on the heap
|
||||||
|
let heap_value = Box::new(41);
|
||||||
|
println!("heap_value at {:p}", heap_value);
|
||||||
|
|
||||||
|
// create a dynamically sized vector
|
||||||
|
let mut vec = Vec::new();
|
||||||
|
for i in 0..500 {
|
||||||
|
vec.push(i);
|
||||||
|
}
|
||||||
|
println!("vec at {:p}", vec.as_slice());
|
||||||
|
|
||||||
|
// create a reference counted vector -> will be freed when count reaches 0
|
||||||
|
let reference_counted = Rc::new(vec![1, 2, 3]);
|
||||||
|
let cloned_reference = reference_counted.clone();
|
||||||
|
println!("current reference count is {}", Rc::strong_count(&cloned_reference));
|
||||||
|
core::mem::drop(reference_counted);
|
||||||
|
println!("reference count is {} now", Rc::strong_count(&cloned_reference));
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
test_main();
|
test_main();
|
||||||
|
|
||||||
@ -21,7 +55,6 @@ pub extern "C" fn _start() -> ! {
|
|||||||
rust_os::hlt_loop();
|
rust_os::hlt_loop();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// This function is called on panic.
|
|
||||||
#[cfg(not(test))]
|
#[cfg(not(test))]
|
||||||
#[panic_handler]
|
#[panic_handler]
|
||||||
fn panic(info: &PanicInfo) -> ! {
|
fn panic(info: &PanicInfo) -> ! {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user