summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDennis Kobert <dennis@kobert.dev>2019-11-08 22:50:13 +0100
committerDennis Kobert <dennis@kobert.dev>2019-11-08 22:50:13 +0100
commit933abe8bc6f9480bcdea39c6bdd1a4e937402a06 (patch)
treeb6679b8e3c68fd71e59ec3ba22fe086525ddd3bc
parentf3dcfa225a6e3b7e6916e9b5a22db9090275d065 (diff)
Add InterruptStackTable
-rw-r--r--kernel/src/boot.asm35
-rw-r--r--kernel/src/interrupts/exceptions.rs15
-rw-r--r--kernel/src/interrupts/gdt.rs61
-rw-r--r--kernel/src/interrupts/mod.rs1
-rw-r--r--kernel/src/interrupts/table.rs11
-rw-r--r--kernel/src/lib.rs19
-rw-r--r--kernel/src/linker.ld4
7 files changed, 113 insertions, 33 deletions
diff --git a/kernel/src/boot.asm b/kernel/src/boot.asm
index 96a1fc1..36b1ef9 100644
--- a/kernel/src/boot.asm
+++ b/kernel/src/boot.asm
@@ -94,27 +94,26 @@ setup_page_tables:
; map each P2 entry to a huge 2MiB page
mov ecx, 0 ; counter variable
- mov eax, 0b10000011 ; present + writable + huge
- mov edx, stack_bottom
- shr edx, 18
+ mov eax, 0b10000011 ; huge + writable + present
.map_p2_table:
- mov ebx, eax
- ; map ecx-th P2 entry to a huge page that starts at address 2MiB*ecx
- cmp ecx, edx
- jne .valid_memory
- add ebx, ~1
- sub eax, 0x200000 ; 2MiB
-
-.valid_memory:
- mov [p2_table + ecx ], ebx ; map ecx-th entry
+ cmp eax, 0b10000011 + stack_bottom
+ jne .valid_mem
+ mov ebx, 0b10000010
+ mov [p2_table + ecx], ebx
+ add ecx, 8
+ cmp ecx, 4096
+ jne .valid_mem
+ ret
+.valid_mem:
+ mov [p2_table + ecx], eax
add eax, 0x200000 ; 2MiB
- add ecx, 8
- cmp ecx, 4096 ; if counter == 512, the whole P2 table is mapped
- jne .map_p2_table ; else map the next entry
-
- ret
+ add ecx, 8
+ cmp ecx, 4096
+ jne .map_p2_table
+
+ ret
enable_paging:
mov eax, p4_table
@@ -167,7 +166,7 @@ p3_table:
resb 4096
p2_table:
resb 4096
-alignb 4096 * 512
+alignb 4096 * 512 ; align memory into huge memory page
stack_bottom:
resb 4096 * 42
stack_top:
diff --git a/kernel/src/interrupts/exceptions.rs b/kernel/src/interrupts/exceptions.rs
index 08555c4..782dd16 100644
--- a/kernel/src/interrupts/exceptions.rs
+++ b/kernel/src/interrupts/exceptions.rs
@@ -4,6 +4,7 @@ use x86_64::structures::idt::{InterruptStackFrame, PageFaultErrorCode};
pub extern "x86-interrupt" fn breakpoint_handler(stack_frame: &mut InterruptStackFrame) {
let mut stdout = OStream::new();
stdout.print(b"EXCEPTION: BREAKPOINT\n");
+ loop {}
}
pub extern "x86-interrupt" fn page_fault_handler(
@@ -13,11 +14,11 @@ pub extern "x86-interrupt" fn page_fault_handler(
use x86_64::registers::control::Cr2;
let mut stdout = OStream::new();
- stdout.print(b"EXCEPTION: PAGEFAULT\n");
- loop {}
- panic!("PAGE FAULT");
- //println!("Accessed Address: {:?}", Cr2::read());
- //println!("Error Code: {:?}", error_code);
+ panic!(
+ "PAGE FAULT while accessing address: {:?}{:?}",
+ Cr2::read(),
+ error_code
+ );
//println!("{:#?}", stack_frame);
}
@@ -25,12 +26,12 @@ pub extern "x86-interrupt" fn segment_not_present_handler(
stack_frame: &mut InterruptStackFrame,
error_code: u64,
) {
- loop {}
let mut stdout = OStream::new();
stdout.print(b"EXCEPTION: SEGMENT NOT PRESENT\n");
+ loop {}
}
-extern "x86-interrupt" fn double_fault_handler(
+pub extern "x86-interrupt" fn double_fault_handler(
stack_frame: &mut InterruptStackFrame,
_error_code: u64,
) {
diff --git a/kernel/src/interrupts/gdt.rs b/kernel/src/interrupts/gdt.rs
new file mode 100644
index 0000000..8f20092
--- /dev/null
+++ b/kernel/src/interrupts/gdt.rs
@@ -0,0 +1,61 @@
+use lazy_static::lazy_static;
+use x86_64::structures::gdt::{Descriptor, GlobalDescriptorTable, SegmentSelector};
+use x86_64::structures::tss::TaskStateSegment;
+use x86_64::VirtAddr;
+
+pub const DOUBLE_FAULT_IST_INDEX: u16 = 0;
+pub const PAGE_FAULT_IST_INDEX: u16 = 1;
+
+lazy_static! {
+ static ref TSS: TaskStateSegment = {
+ let mut tss = TaskStateSegment::new();
+ tss.interrupt_stack_table[DOUBLE_FAULT_IST_INDEX as usize] = {
+ const STACK_SIZE: usize = 4096;
+ static mut STACK: [u8; STACK_SIZE] = [0; STACK_SIZE];
+
+ let stack_start = VirtAddr::from_ptr(unsafe { &STACK });
+ let stack_end = stack_start + STACK_SIZE;
+ stack_end
+ };
+ tss.interrupt_stack_table[PAGE_FAULT_IST_INDEX as usize] = {
+ const STACK_SIZE: usize = 4096;
+ static mut STACK: [u8; STACK_SIZE] = [0; STACK_SIZE];
+
+ let stack_start = VirtAddr::from_ptr(unsafe { &STACK });
+ let stack_end = stack_start + STACK_SIZE;
+ stack_end
+ };
+ tss
+ };
+}
+
+lazy_static! {
+ static ref GDT: (GlobalDescriptorTable, Selectors) = {
+ let mut gdt = GlobalDescriptorTable::new();
+ let code_selector = gdt.add_entry(Descriptor::kernel_code_segment());
+ let tss_selector = gdt.add_entry(Descriptor::tss_segment(&TSS));
+ (
+ gdt,
+ Selectors {
+ code_selector,
+ tss_selector,
+ },
+ )
+ };
+}
+
+struct Selectors {
+ code_selector: SegmentSelector,
+ tss_selector: SegmentSelector,
+}
+
+pub fn init() {
+ use x86_64::instructions::segmentation::set_cs;
+ use x86_64::instructions::tables::load_tss;
+
+ GDT.0.load();
+ unsafe {
+ set_cs(GDT.1.code_selector);
+ load_tss(GDT.1.tss_selector);
+ }
+}
diff --git a/kernel/src/interrupts/mod.rs b/kernel/src/interrupts/mod.rs
index ae21761..14de3f2 100644
--- a/kernel/src/interrupts/mod.rs
+++ b/kernel/src/interrupts/mod.rs
@@ -1,2 +1,3 @@
mod exceptions;
+pub mod gdt;
pub mod table;
diff --git a/kernel/src/interrupts/table.rs b/kernel/src/interrupts/table.rs
index 6472014..d417824 100644
--- a/kernel/src/interrupts/table.rs
+++ b/kernel/src/interrupts/table.rs
@@ -7,10 +7,17 @@ lazy_static! {
let mut idt = InterruptDescriptorTable::new();
idt.breakpoint
.set_handler_fn(super::exceptions::breakpoint_handler);
- idt.page_fault
- .set_handler_fn(super::exceptions::page_fault_handler);
idt.segment_not_present
.set_handler_fn(super::exceptions::segment_not_present_handler);
+ unsafe {
+ idt.double_fault
+ .set_handler_fn(super::exceptions::double_fault_handler)
+ .set_stack_index(super::gdt::DOUBLE_FAULT_IST_INDEX);
+ idt.page_fault
+ .set_handler_fn(super::exceptions::page_fault_handler)
+ .set_stack_index(super::gdt::PAGE_FAULT_IST_INDEX);
+ }
+
idt
};
}
diff --git a/kernel/src/lib.rs b/kernel/src/lib.rs
index 8ec68e5..15f027b 100644
--- a/kernel/src/lib.rs
+++ b/kernel/src/lib.rs
@@ -26,6 +26,7 @@ pub fn test_runner(tests: &[&dyn Fn(&mut OStream)]) {
#[no_mangle]
pub extern "C" fn _start() -> ! {
+ interrupts::gdt::init();
interrupts::table::init();
if cfg!(test) {
#[cfg(test)]
@@ -37,10 +38,19 @@ pub extern "C" fn _start() -> ! {
stdout.clear();
panic!("panic! at the disco");
- core::iter::successors(Some(0), |n| Some(n + 1))
- .for_each(|n| write!(&mut stdout, "hello world {}!", n).unwrap());
-
- x86_64::instructions::interrupts::int3();
+ /// TODO: write test
+ ///fn _loop(i: u64) -> u64 {
+ /// if i > 0b1010101001101101 {
+ /// return i;
+ /// }
+ /// let n = i;
+ /// let mut stdout = OStream::new();
+ /// write!(&mut stdout, "{:x}", &n as *const u64 as u64).unwrap();
+ /// _loop(i + 1)
+ ///}
+ ///_loop(0);
+ /// TODO: write test
+ ///x86_64::instructions::interrupts::int3();
loop {}
}
@@ -72,7 +82,6 @@ pub extern "C" fn panic_handler(info: &core::panic::PanicInfo) -> ! {
info.message()
.unwrap_or(&format_args!("no panic information obtainable"))
);
- //loop{}
stderr.set_centered(false);
if cfg!(test) {
write!(serial::SerialStream::new(), "Testing failed\n").unwrap();
diff --git a/kernel/src/linker.ld b/kernel/src/linker.ld
index d187fd2..cca621e 100644
--- a/kernel/src/linker.ld
+++ b/kernel/src/linker.ld
@@ -13,7 +13,7 @@ SECTIONS {
{
*(.text)
}
- rodata :
+ .rodata :
{
*(.rodata)
}
@@ -21,4 +21,6 @@ SECTIONS {
{
*(.bss)
}
+ /*[Guard page]*/
+ . += 2M;
}