mirror of
https://github.com/phil-opp/blog_os.git
synced 2025-12-16 22:37:49 +00:00
Reset source code to master again
This commit is contained in:
@@ -4,11 +4,10 @@ name = "blog_os"
|
|||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
bit_field = "0.1.0"
|
|
||||||
bitflags = "0.7.0"
|
|
||||||
once = "0.2.1"
|
once = "0.2.1"
|
||||||
rlibc = "0.1.4"
|
rlibc = "0.1.4"
|
||||||
spin = "0.3.4"
|
spin = "0.3.4"
|
||||||
|
bitflags = "0.7.0"
|
||||||
|
|
||||||
[dependencies.hole_list_allocator]
|
[dependencies.hole_list_allocator]
|
||||||
path = "libs/hole_list_allocator"
|
path = "libs/hole_list_allocator"
|
||||||
@@ -18,7 +17,7 @@ git = "https://github.com/phil-opp/multiboot2-elf64"
|
|||||||
|
|
||||||
[dependencies.x86]
|
[dependencies.x86]
|
||||||
default-features = false
|
default-features = false
|
||||||
version = "0.7.0"
|
version = "0.6.0"
|
||||||
|
|
||||||
[lib]
|
[lib]
|
||||||
crate-type = ["staticlib"]
|
crate-type = ["staticlib"]
|
||||||
|
|||||||
@@ -1,115 +0,0 @@
|
|||||||
use bit_field::BitField;
|
|
||||||
use collections::vec::Vec;
|
|
||||||
use core::ops::Range;
|
|
||||||
use x86::task::TaskStateSegment;
|
|
||||||
|
|
||||||
pub struct Gdt(Vec<BitField<u64>>);
|
|
||||||
|
|
||||||
impl Gdt {
|
|
||||||
pub fn new() -> Gdt {
|
|
||||||
let zero_entry = BitField::new(0);
|
|
||||||
Gdt(vec![zero_entry])
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn add_entry(&mut self, entry: Entry) -> Selector {
|
|
||||||
use core::mem::size_of;
|
|
||||||
let index = self.0.len() * size_of::<BitField<u64>>();
|
|
||||||
|
|
||||||
match entry {
|
|
||||||
Entry::UserSegment(entry) => self.0.push(entry),
|
|
||||||
Entry::SystemSegment(entry_low, entry_high) => {
|
|
||||||
self.0.push(entry_low);
|
|
||||||
self.0.push(entry_high);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Selector(index as u16)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub unsafe fn load(&'static self) {
|
|
||||||
use x86::dtables::{DescriptorTablePointer, lgdt};
|
|
||||||
use core::mem::{self, size_of};
|
|
||||||
|
|
||||||
let ptr = DescriptorTablePointer {
|
|
||||||
base: self.0.as_ptr() as u64,
|
|
||||||
limit: (self.0.len() * size_of::<u64>() - 1) as u16,
|
|
||||||
};
|
|
||||||
|
|
||||||
lgdt(&ptr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub enum Entry {
|
|
||||||
UserSegment(BitField<u64>),
|
|
||||||
SystemSegment(BitField<u64>, BitField<u64>),
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Entry {
|
|
||||||
pub fn code_segment() -> Entry {
|
|
||||||
let flags = DESCRIPTOR_TYPE | PRESENT | READ_WRITE | EXECUTABLE | LONG_MODE;
|
|
||||||
Entry::UserSegment(BitField::new(flags.bits()))
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn data_segment() -> Entry {
|
|
||||||
let flags = DESCRIPTOR_TYPE | PRESENT | READ_WRITE;
|
|
||||||
Entry::UserSegment(BitField::new(flags.bits()))
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn tss_segment(tss: &'static TaskStateSegment) -> Entry {
|
|
||||||
use core::mem::size_of;
|
|
||||||
|
|
||||||
let ptr = BitField::new(tss as *const _ as u64);
|
|
||||||
|
|
||||||
let mut low = BitField::new(PRESENT.bits());
|
|
||||||
low.set_range(0..16, (size_of::<TaskStateSegment>() - 1) as u64);
|
|
||||||
low.set_range(16..40, ptr.get_range(0..24));
|
|
||||||
low.set_range(40..44, 0b1001); // type: available 64-bit tss
|
|
||||||
|
|
||||||
let mut high = BitField::new(0);
|
|
||||||
high.set_range(0..32, ptr.get_range(32..64));
|
|
||||||
|
|
||||||
Entry::SystemSegment(low, high)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bitflags! {
|
|
||||||
flags EntryFlags: u64 {
|
|
||||||
const READ_WRITE = 1 << 41,
|
|
||||||
const CONFORMING = 1 << 42,
|
|
||||||
const EXECUTABLE = 1 << 43,
|
|
||||||
const DESCRIPTOR_TYPE = 1 << 44,
|
|
||||||
const PRESENT = 1 << 47,
|
|
||||||
const LONG_MODE = 1 << 53,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy)]
|
|
||||||
pub struct Selector(u16);
|
|
||||||
|
|
||||||
pub fn reload_segment_registers(code_selector: Selector, data_selector: Selector) {
|
|
||||||
|
|
||||||
let current_code_selector: u16;
|
|
||||||
let current_data_selector: u16;
|
|
||||||
|
|
||||||
unsafe {
|
|
||||||
asm!("mov $0, cs" : "=r" (current_code_selector) ::: "intel");
|
|
||||||
asm!("mov $0, ds" : "=r" (current_data_selector) ::: "intel");
|
|
||||||
}
|
|
||||||
assert_eq!(code_selector.0, current_code_selector);
|
|
||||||
assert_eq!(data_selector.0, current_data_selector);
|
|
||||||
|
|
||||||
// jmp ax:.new_code_segment // TODO
|
|
||||||
// .new_code_segment:
|
|
||||||
// unsafe { asm!("
|
|
||||||
// mov ax, $1
|
|
||||||
// mov ss, ax
|
|
||||||
// mov ds, ax
|
|
||||||
// mov es, ax
|
|
||||||
// ":: "r" (code_selector.0), "r" (data_selector.0) :: "intel")};
|
|
||||||
//
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Load the task state register.
|
|
||||||
pub unsafe fn load_ltr(selector: Selector) {
|
|
||||||
asm!("ltr $0" :: "r" (selector));
|
|
||||||
}
|
|
||||||
@@ -1,101 +0,0 @@
|
|||||||
use x86::segmentation::{self, SegmentSelector};
|
|
||||||
|
|
||||||
pub struct Idt([Entry; 16]);
|
|
||||||
|
|
||||||
impl Idt {
|
|
||||||
pub fn new() -> Idt {
|
|
||||||
Idt([Entry::missing(); 16])
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn set_handler(&mut self, entry: u8, handler: extern "C" fn() -> !) -> &mut EntryOptions {
|
|
||||||
self.0[entry as usize] = Entry::new(segmentation::cs(), handler);
|
|
||||||
&mut self.0[entry as usize].options
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn load(&'static self) {
|
|
||||||
use x86::dtables::{DescriptorTablePointer, lidt};
|
|
||||||
use core::mem::size_of;
|
|
||||||
|
|
||||||
let ptr = DescriptorTablePointer {
|
|
||||||
base: self as *const _ as u64,
|
|
||||||
limit: (size_of::<Self>() - 1) as u16,
|
|
||||||
};
|
|
||||||
|
|
||||||
unsafe { lidt(&ptr) };
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
use bit_field::BitField;
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy)]
|
|
||||||
#[repr(C, packed)]
|
|
||||||
pub struct Entry {
|
|
||||||
pointer_low: u16,
|
|
||||||
gdt_selector: SegmentSelector,
|
|
||||||
options: EntryOptions,
|
|
||||||
pointer_middle: u16,
|
|
||||||
pointer_high: u32,
|
|
||||||
reserved: u32,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Entry {
|
|
||||||
fn missing() -> Self {
|
|
||||||
Entry {
|
|
||||||
gdt_selector: SegmentSelector::new(0),
|
|
||||||
pointer_low: 0,
|
|
||||||
pointer_middle: 0,
|
|
||||||
pointer_high: 0,
|
|
||||||
options: EntryOptions::minimal(),
|
|
||||||
reserved: 0,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn new(gdt_selector: SegmentSelector, handler: extern "C" fn() -> !) -> Self {
|
|
||||||
let pointer = handler as u64;
|
|
||||||
Entry {
|
|
||||||
gdt_selector: gdt_selector,
|
|
||||||
pointer_low: pointer as u16,
|
|
||||||
pointer_middle: (pointer >> 16) as u16,
|
|
||||||
pointer_high: (pointer >> 32) as u32,
|
|
||||||
options: EntryOptions::new(),
|
|
||||||
reserved: 0,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy)]
|
|
||||||
pub struct EntryOptions(BitField<u16>);
|
|
||||||
|
|
||||||
impl EntryOptions {
|
|
||||||
fn minimal() -> Self {
|
|
||||||
let mut options = BitField::new(0);
|
|
||||||
options.set_range(9..12, 0b111); // required 'one' bits
|
|
||||||
EntryOptions(options)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn new() -> Self {
|
|
||||||
let mut options = Self::minimal();
|
|
||||||
options.set_present(true);
|
|
||||||
options
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn set_present(&mut self, present: bool) -> &mut Self {
|
|
||||||
self.0.set_bit(15, present);
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn disable_interrupts(&mut self, disable: bool) -> &mut Self {
|
|
||||||
self.0.set_bit(8, !disable);
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn set_privilege_level(&mut self, dpl: u16) -> &mut Self {
|
|
||||||
self.0.set_range(13..15, dpl);
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn set_stack_index(&mut self, index: u16) -> &mut Self {
|
|
||||||
self.0.set_range(0..3, index);
|
|
||||||
self
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,90 +0,0 @@
|
|||||||
use x86::task::{load_ltr, TaskStateSegment};
|
|
||||||
use vga_buffer::print_error;
|
|
||||||
|
|
||||||
mod idt;
|
|
||||||
mod gdt;
|
|
||||||
|
|
||||||
lazy_static! {
|
|
||||||
static ref IDT: idt::Idt = {
|
|
||||||
let mut idt = idt::Idt::new();
|
|
||||||
|
|
||||||
idt.set_handler(0, divide_by_zero_handler);
|
|
||||||
idt.set_handler(8, double_fault_handler).set_stack_index(1);
|
|
||||||
idt.set_handler(13, general_protection_fault_handler);
|
|
||||||
idt.set_handler(14, page_fault_handler);
|
|
||||||
|
|
||||||
idt
|
|
||||||
};
|
|
||||||
|
|
||||||
static ref TSS: TaskStateSegment = {
|
|
||||||
let mut tss = TaskStateSegment::new();
|
|
||||||
|
|
||||||
let stack_size = 1024 * 3; // 3KiB
|
|
||||||
let stack_bottom = unsafe {
|
|
||||||
::alloc::heap::allocate(stack_size, 16) as usize // TODO
|
|
||||||
};
|
|
||||||
let stack_top = stack_bottom + stack_size;
|
|
||||||
|
|
||||||
tss.ist[0] = stack_top as u64;
|
|
||||||
|
|
||||||
tss
|
|
||||||
};
|
|
||||||
|
|
||||||
static ref GDT: Gdt = {
|
|
||||||
let mut table = gdt::Gdt::new();
|
|
||||||
|
|
||||||
let selectors = GdtSelectors {
|
|
||||||
code: table.add_entry(gdt::Entry::code_segment()),
|
|
||||||
data: table.add_entry(gdt::Entry::data_segment()),
|
|
||||||
tss: table.add_entry(gdt::Entry::tss_segment(&TSS)),
|
|
||||||
};
|
|
||||||
|
|
||||||
Gdt {
|
|
||||||
table: table,
|
|
||||||
selectors: selectors,
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
struct Gdt {
|
|
||||||
table: gdt::Gdt,
|
|
||||||
selectors: GdtSelectors,
|
|
||||||
}
|
|
||||||
|
|
||||||
struct GdtSelectors {
|
|
||||||
code: gdt::Selector,
|
|
||||||
data: gdt::Selector,
|
|
||||||
tss: gdt::Selector,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn init() {
|
|
||||||
assert_has_not_been_called!();
|
|
||||||
|
|
||||||
unsafe {
|
|
||||||
GDT.table.load();
|
|
||||||
gdt::reload_segment_registers(GDT.selectors.code, GDT.selectors.data);
|
|
||||||
gdt::load_ltr(GDT.selectors.tss);
|
|
||||||
}
|
|
||||||
IDT.load();
|
|
||||||
}
|
|
||||||
|
|
||||||
extern "C" fn divide_by_zero_handler() -> ! {
|
|
||||||
unsafe { print_error(format_args!("EXCEPTION: DIVIDE BY ZERO")) };
|
|
||||||
loop {}
|
|
||||||
}
|
|
||||||
|
|
||||||
extern "C" fn double_fault_handler() -> ! {
|
|
||||||
unsafe { print_error(format_args!("EXCEPTION: DOUBLE FAULT")) };
|
|
||||||
unsafe { asm!("iretq")};
|
|
||||||
loop {}
|
|
||||||
}
|
|
||||||
|
|
||||||
extern "C" fn general_protection_fault_handler() -> ! {
|
|
||||||
unsafe { print_error(format_args!("EXCEPTION: GENERAL PROTECTION FAULT")) };
|
|
||||||
loop {}
|
|
||||||
}
|
|
||||||
|
|
||||||
extern "C" fn page_fault_handler() -> ! {
|
|
||||||
unsafe { print_error(format_args!("EXCEPTION: PAGE FAULT")) };
|
|
||||||
loop {}
|
|
||||||
}
|
|
||||||
30
src/lib.rs
30
src/lib.rs
@@ -10,9 +10,6 @@
|
|||||||
#![feature(lang_items)]
|
#![feature(lang_items)]
|
||||||
#![feature(const_fn, unique)]
|
#![feature(const_fn, unique)]
|
||||||
#![feature(alloc, collections)]
|
#![feature(alloc, collections)]
|
||||||
#![feature(asm)]
|
|
||||||
#![feature(drop_types_in_const)]
|
|
||||||
#![feature(heap_api)]
|
|
||||||
#![no_std]
|
#![no_std]
|
||||||
|
|
||||||
extern crate rlibc;
|
extern crate rlibc;
|
||||||
@@ -29,12 +26,9 @@ extern crate alloc;
|
|||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate collections;
|
extern crate collections;
|
||||||
|
|
||||||
extern crate bit_field;
|
|
||||||
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
mod vga_buffer;
|
mod vga_buffer;
|
||||||
mod memory;
|
mod memory;
|
||||||
mod interrupts;
|
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub extern "C" fn rust_main(multiboot_information_address: usize) {
|
pub extern "C" fn rust_main(multiboot_information_address: usize) {
|
||||||
@@ -49,20 +43,11 @@ pub extern "C" fn rust_main(multiboot_information_address: usize) {
|
|||||||
// set up guard page and map the heap pages
|
// set up guard page and map the heap pages
|
||||||
memory::init(boot_info);
|
memory::init(boot_info);
|
||||||
|
|
||||||
interrupts::init();
|
use alloc::boxed::Box;
|
||||||
|
let heap_test = Box::new(42);
|
||||||
|
|
||||||
//println!("{:?}", unsafe { *(0xdeadbeaf as *mut u32) });
|
for i in 0..10000 {
|
||||||
//unsafe { *(0xdeadbeaf as *mut u32) = 42 };
|
format!("Some String");
|
||||||
|
|
||||||
fn recursive() {
|
|
||||||
recursive();
|
|
||||||
}
|
|
||||||
recursive();
|
|
||||||
|
|
||||||
unsafe { *(0xdeadbeaf as *mut u32) = 42 };
|
|
||||||
|
|
||||||
unsafe {
|
|
||||||
asm!("xor eax, eax; idiv eax" :::: "intel");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
println!("It did not crash!");
|
println!("It did not crash!");
|
||||||
@@ -94,11 +79,8 @@ extern "C" fn eh_personality() {}
|
|||||||
#[cfg(not(test))]
|
#[cfg(not(test))]
|
||||||
#[lang = "panic_fmt"]
|
#[lang = "panic_fmt"]
|
||||||
extern "C" fn panic_fmt(fmt: core::fmt::Arguments, file: &str, line: u32) -> ! {
|
extern "C" fn panic_fmt(fmt: core::fmt::Arguments, file: &str, line: u32) -> ! {
|
||||||
use vga_buffer::print_error;
|
println!("\n\nPANIC in {} at line {}:", file, line);
|
||||||
unsafe {
|
println!(" {}", fmt);
|
||||||
print_error(format_args!("\n\nPANIC in {} at line {}:", file, line));
|
|
||||||
print_error(format_args!(" {}", fmt));
|
|
||||||
}
|
|
||||||
loop {}
|
loop {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -135,15 +135,3 @@ struct ScreenChar {
|
|||||||
struct Buffer {
|
struct Buffer {
|
||||||
chars: [[ScreenChar; BUFFER_WIDTH]; BUFFER_HEIGHT],
|
chars: [[ScreenChar; BUFFER_WIDTH]; BUFFER_HEIGHT],
|
||||||
}
|
}
|
||||||
|
|
||||||
pub unsafe fn print_error(fmt: fmt::Arguments) {
|
|
||||||
use core::fmt::Write;
|
|
||||||
|
|
||||||
let mut writer = Writer {
|
|
||||||
column_position: 0,
|
|
||||||
color_code: ColorCode::new(Color::Red, Color::Black),
|
|
||||||
buffer: Unique::new(0xb8000 as *mut _),
|
|
||||||
};
|
|
||||||
writer.new_line();
|
|
||||||
writer.write_fmt(fmt);
|
|
||||||
}
|
|
||||||
|
|||||||
Reference in New Issue
Block a user