Compare commits

..

28 Commits

Author SHA1 Message Date
Philipp Oppermann
df3917dfbf Update to latest bit_field version
(cherry picked from commit 46100ba24b)
2017-01-25 13:51:55 +01:00
Philipp Oppermann
9d4a761be7 The ReadWrite flag isn't needed for code segments (#279)
(cherry picked from commit fce85e68ee)
2017-01-18 13:13:55 +01:00
Philipp Oppermann
43ef84d68a Load null selectors to all data registers
This is required for some instructions such as iretq (ss must be valid or 0).

(cherry picked from commit 8f8b46a9b6)
2017-01-15 14:18:32 +01:00
Philipp Oppermann
b3ddd18e7a Data segments aren't needed for 64-bit mode
(cherry picked from commit e179dadf70)
2017-01-15 14:14:43 +01:00
Philipp Oppermann
d905671f45 Make panic_fmt public to fix private_no_mangle_fns warning
(cherry picked from commit 1be2f42791)
2017-01-04 16:24:32 +01:00
Philipp Oppermann
a46b3a13c4 Mark panic_fmt as no_mangle to work around rust-lang/rust#38281
(cherry picked from commit 081105bbb6)
(cherry picked from commit 1acc1ff5806f2fa101f726644d258eb4e4543540)
2017-01-04 16:10:29 +01:00
Philipp Oppermann
7c8f62d312 Update x86 crate to version 0.8.0 (#266)
(cherry picked from commit 02697891e2)
2016-12-21 15:08:28 +01:00
Philipp Oppermann
fdec350e85 Remove cargo workspace (#265)
(cherry picked from commit fcd453ac29)
2016-12-21 14:46:47 +01:00
Philipp Oppermann
d0bb3f847a Fix panic_fmt arguments: file is a &'static str
(cherry picked from commit e9735738f7)
2016-11-26 12:29:29 +01:00
Philipp Oppermann
041aa2bfe6 Remove print_error and use normal println in exception handlers
(cherry picked from commit 9b83b2853e)
2016-10-31 01:27:10 +01:00
Philipp Oppermann
02b8078e1d Create a new print function and use it in the print macro
This fixes the deadlock problem, because the format_args is now evaluated before locking the screen writer. So `println!("{:?}", {println!("");})` no longer triggers a deadlock.

(cherry picked from commit d96df500a7)
2016-10-31 01:20:19 +01:00
Philipp Oppermann
351ae60205 Use volatile operations for accessing the VGA buffer
(cherry picked from commit d7a445b1bb)
2016-10-08 15:55:25 +02:00
Philipp Oppermann
b050b475f7 Add missing license headers and update copyright year (#232)
(cherry picked from commit a04924955a)
2016-10-02 18:31:18 +02:00
Philipp Oppermann
29fd8983c5 Add missing license headers (#233)
(cherry picked from commit 0f4d1ce303)
2016-10-02 18:29:49 +02:00
Philipp Oppermann
40bc3e9059 Use crates.io version of multiboot2
(cherry picked from commit c6b1346956)
2016-09-27 13:55:52 +02:00
Calvin Lee
30a75ec760 Fixes #220: BumpAllocator overflow
I also fixed a spelling error and replaced a tab with a space
in the blog post where `allocate()` was created.

(cherry picked from commit 54e02fd6b5)
(cherry picked from commit 3a2f0b33297164ebbfab92ee76881b6c06c4914d)
2016-09-27 13:40:58 +02:00
Philipp Oppermann
19f0b5443a Update bit_field to 0.5.0 and use new API
(cherry picked from commit 6eba03dd58)
2016-09-27 13:38:13 +02:00
Philipp Oppermann
689bd2e3e2 Create a cargo workspace for subcrates
(cherry picked from commit 488a3c16f0)
2016-08-05 11:28:05 +02:00
Philipp Oppermann
f5af9e25e4 Add aligned .got and .got.plt sections to linker script
(cherry picked from commit 2445b47661)
2016-07-16 17:23:50 +02:00
Philipp Oppermann
0a7843abd9 Catch divide error instead of page fault
The divide error pushes no error code. Thus we avoid stack misalignment (see #184).

(cherry picked from commit e8b3a1fff1)
2016-06-25 17:22:31 +02:00
Philipp Oppermann
dcab71016c Create dummy _Unwind_Resume function to fix libcore linker errors
(cherry picked from commit 952f7ed5e3)
2016-06-24 13:49:43 +02:00
Philipp Oppermann
3f4f2b8ac2 Revert "Remove unneeded gcc_except_table section" (#180)
(cherry picked from commit 76b83c623e)
2016-06-13 18:38:49 +02:00
Philipp Oppermann
428f97d049 Remove unneeded gcc_except_table section
(cherry picked from commit 1083ac9bac)
2016-06-12 16:37:40 +02:00
Philipp Oppermann
69b22d1fc0 Use the panic=abort option instead of -Z no-landing-pads
(cherry picked from commit 725c452157)
2016-06-12 16:22:02 +02:00
Philipp Oppermann
20f7e5472b Make methods of EntryOptions public
(cherry picked from commit 480265872d)
2016-05-29 17:26:28 +02:00
Philipp Oppermann
534d23c80f Fix .travis.yml for tag build 2016-05-28 15:58:12 +02:00
Philipp Oppermann
8c8f9dbb68 Update README for catching_exceptions tag 2016-05-28 15:54:33 +02:00
Philipp Oppermann
77f3ca3483 Remove blog and script subdirectories 2016-05-28 15:52:58 +02:00
9 changed files with 36 additions and 111 deletions

View File

@@ -15,4 +15,5 @@ addons:
packages:
- nasm
script: make
script:
- make

View File

@@ -1,7 +1,7 @@
# Blog OS (Better Exception Messages)
[![Build Status](https://travis-ci.org/phil-opp/blog_os.svg?branch=better_exception_messages)](https://travis-ci.org/phil-opp/blog_os/branches)
# Blog OS (Catching Exceptions)
[![Build Status](https://travis-ci.org/phil-opp/blog_os.svg?branch=catching_exceptions)](https://travis-ci.org/phil-opp/blog_os/branches)
This repository contains the source code for the [Better Exception Messages](http://os.phil-opp.com/better-exception-messages.html) post of the [Writing an OS in Rust](http://os.phil-opp.com) series.
This repository contains the source code for the [Catching Exceptions](http://os.phil-opp.com/catching-exceptions.html) post of the [Writing an OS in Rust](http://os.phil-opp.com) series.
**Check out the [master branch](https://github.com/phil-opp/blog_os) for more information.**

View File

@@ -101,13 +101,11 @@ impl EntryOptions {
self
}
#[allow(dead_code)]
pub fn set_privilege_level(&mut self, dpl: u16) -> &mut Self {
self.0.set_bits(13..15, dpl);
self
}
#[allow(dead_code)]
pub fn set_stack_index(&mut self, index: u16) -> &mut Self {
self.0.set_bits(0..3, index);
self

View File

@@ -9,50 +9,11 @@
mod idt;
macro_rules! handler {
($name: ident) => {{
#[naked]
extern "C" fn wrapper() -> ! {
unsafe {
asm!("mov rdi, rsp
sub rsp, 8 // align the stack pointer
call $0"
:: "i"($name as extern "C" fn(
&ExceptionStackFrame) -> !)
: "rdi" : "intel");
::core::intrinsics::unreachable();
}
}
wrapper
}}
}
macro_rules! handler_with_error_code {
($name: ident) => {{
#[naked]
extern "C" fn wrapper() -> ! {
unsafe {
asm!("pop rsi // pop error code into rsi
mov rdi, rsp
sub rsp, 8 // align the stack pointer
call $0"
:: "i"($name as extern "C" fn(
&ExceptionStackFrame, u64) -> !)
: "rdi","rsi" : "intel");
::core::intrinsics::unreachable();
}
}
wrapper
}}
}
lazy_static! {
static ref IDT: idt::Idt = {
let mut idt = idt::Idt::new();
idt.set_handler(0, handler!(divide_by_zero_handler));
idt.set_handler(6, handler!(invalid_opcode_handler));
idt.set_handler(14, handler_with_error_code!(page_fault_handler));
idt.set_handler(0, divide_by_zero_handler);
idt
};
@@ -62,44 +23,7 @@ pub fn init() {
IDT.load();
}
#[derive(Debug)]
#[repr(C)]
struct ExceptionStackFrame {
instruction_pointer: u64,
code_segment: u64,
cpu_flags: u64,
stack_pointer: u64,
stack_segment: u64,
}
extern "C" fn divide_by_zero_handler(stack_frame: &ExceptionStackFrame) -> ! {
println!("\nEXCEPTION: DIVIDE BY ZERO\n{:#?}", stack_frame);
loop {}
}
extern "C" fn invalid_opcode_handler(stack_frame: &ExceptionStackFrame) -> ! {
println!("\nEXCEPTION: INVALID OPCODE at {:#x}\n{:#?}",
stack_frame.instruction_pointer,
stack_frame);
loop {}
}
bitflags! {
flags PageFaultErrorCode: u64 {
const PROTECTION_VIOLATION = 1 << 0,
const CAUSED_BY_WRITE = 1 << 1,
const USER_MODE = 1 << 2,
const MALFORMED_TABLE = 1 << 3,
const INSTRUCTION_FETCH = 1 << 4,
}
}
extern "C" fn page_fault_handler(stack_frame: &ExceptionStackFrame, error_code: u64) -> ! {
use x86::shared::control_regs;
println!("\nEXCEPTION: PAGE FAULT while accessing {:#x}\nerror code: \
{:?}\n{:#?}",
unsafe { control_regs::cr2() },
PageFaultErrorCode::from_bits(error_code).unwrap(),
stack_frame);
extern "C" fn divide_by_zero_handler() -> ! {
println!("EXCEPTION: DIVIDE BY ZERO");
loop {}
}

View File

@@ -11,8 +11,6 @@
#![feature(const_fn, unique)]
#![feature(alloc, collections)]
#![feature(asm)]
#![feature(naked_functions)]
#![feature(core_intrinsics)]
#![no_std]
extern crate rlibc;
@@ -53,9 +51,12 @@ pub extern "C" fn rust_main(multiboot_information_address: usize) {
// initialize our IDT
interrupts::init();
// provoke a page fault
unsafe { *(0xdeadbeaf as *mut u64) = 42 };
fn divide_by_zero() {
unsafe { asm!("mov dx, 0; div dx" ::: "ax", "dx" : "volatile", "intel") }
}
// provoke a divide by zero fault inside println
println!("{:?}", divide_by_zero());
println!("It did not crash!");
loop {}

View File

@@ -47,12 +47,13 @@ impl AreaFrameAllocator {
fn choose_next_area(&mut self) {
self.current_area = self.areas
.clone()
.filter(|area| {
let address = area.base_addr + area.length - 1;
Frame::containing_address(address as usize) >= self.next_free_frame
})
.min_by_key(|area| area.base_addr);
.clone()
.filter(|area| {
let address = area.base_addr + area.length - 1;
Frame::containing_address(address as usize) >=
self.next_free_frame
})
.min_by_key(|area| area.base_addr);
if let Some(area) = self.current_area {
let start_frame = Frame::containing_address(area.base_addr as usize);

View File

@@ -24,15 +24,15 @@ pub fn init(boot_info: &BootInformation) {
let elf_sections_tag = boot_info.elf_sections_tag().expect("Elf sections tag required");
let kernel_start = elf_sections_tag.sections()
.filter(|s| s.is_allocated())
.map(|s| s.addr)
.min()
.unwrap();
.filter(|s| s.is_allocated())
.map(|s| s.addr)
.min()
.unwrap();
let kernel_end = elf_sections_tag.sections()
.filter(|s| s.is_allocated())
.map(|s| s.addr + s.size)
.max()
.unwrap();
.filter(|s| s.is_allocated())
.map(|s| s.addr + s.size)
.max()
.unwrap();
println!("kernel start: {:#x}, kernel end: {:#x}",
kernel_start,

View File

@@ -69,9 +69,9 @@ impl Mapper {
};
p3.and_then(|p3| p3.next_table(page.p3_index()))
.and_then(|p2| p2.next_table(page.p2_index()))
.and_then(|p1| p1[page.p1_index()].pointed_frame())
.or_else(huge_page)
.and_then(|p2| p2.next_table(page.p2_index()))
.and_then(|p1| p1[page.p1_index()].pointed_frame())
.or_else(huge_page)
}
pub fn map_to<A>(&mut self, page: Page, frame: Frame, flags: EntryFlags, allocator: &mut A)
@@ -105,10 +105,10 @@ impl Mapper {
assert!(self.translate(page.start_address()).is_some());
let p1 = self.p4_mut()
.next_table_mut(page.p4_index())
.and_then(|p3| p3.next_table_mut(page.p3_index()))
.and_then(|p2| p2.next_table_mut(page.p2_index()))
.expect("mapping code does not support huge pages");
.next_table_mut(page.p4_index())
.and_then(|p3| p3.next_table_mut(page.p3_index()))
.and_then(|p2| p2.next_table_mut(page.p2_index()))
.expect("mapping code does not support huge pages");
let frame = p1[page.p1_index()].pointed_frame().unwrap();
p1[page.p1_index()].set_unused();
unsafe { ::x86::shared::tlb::flush(page.start_address()) };

View File

@@ -180,7 +180,7 @@ pub fn remap_the_kernel<A>(allocator: &mut A, boot_info: &BootInformation) -> Ac
active_table.with(&mut new_table, &mut temporary_page, |mapper| {
let elf_sections_tag = boot_info.elf_sections_tag()
.expect("Memory map tag required");
.expect("Memory map tag required");
// identity map the allocated kernel sections
for section in elf_sections_tag.sections() {