summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDennis Kobert <dennis@kobert.dev>2019-11-09 03:14:44 +0100
committerDennis Kobert <dennis@kobert.dev>2019-11-09 03:14:44 +0100
commit3c2d0f630082c81e7d79e792310ae70629cea052 (patch)
treedc281e21fd6e2a414eaf58423df47ef958491e34
parent1e0422eb84988464836a8f17fd7420b9f3cf277b (diff)
parentd7ca45f9986f1aef6cee256a581a38f824e21585 (diff)
Merge branch 'exceptions' of https://git.kobert.dev/uff-os into exceptions
-rw-r--r--kernel/src/interrupts/exceptions.rs32
-rw-r--r--kernel/src/io/mod.rs1
-rw-r--r--kernel/src/io/panic_screen.rs57
-rw-r--r--kernel/src/io/vga_text.rs34
-rw-r--r--kernel/src/lib.rs33
5 files changed, 89 insertions, 68 deletions
diff --git a/kernel/src/interrupts/exceptions.rs b/kernel/src/interrupts/exceptions.rs
index b6fb5a6..057adbc 100644
--- a/kernel/src/interrupts/exceptions.rs
+++ b/kernel/src/interrupts/exceptions.rs
@@ -1,11 +1,19 @@
use x86_64::structures::idt::{InterruptStackFrame, PageFaultErrorCode};
+macro_rules! exception_default {
+ ($stack_frame: expr) => {
+ format_args!("instruction addr: 0x{:08x}\nstack addr: 0x{:08x}\nflags: 0x{:x}",
+ $stack_frame.instruction_pointer.as_u64(),
+ $stack_frame.cpu_flags,
+ $stack_frame.stack_pointer.as_u64()
+ )
+ }
+}
+
pub extern "x86-interrupt" fn breakpoint_handler(stack_frame: &mut InterruptStackFrame) {
panic!(
- "BREAKPOINT at {:x} Flags: {:b} Stack: {:x}",
- stack_frame.instruction_pointer.as_u64(),
- stack_frame.cpu_flags,
- stack_frame.stack_pointer.as_u64()
+ "BREAKPOINT exception thrown\n\n{}",
+ exception_default!(stack_frame)
);
}
@@ -16,11 +24,11 @@ pub extern "x86-interrupt" fn page_fault_handler(
use x86_64::registers::control::Cr2;
panic!(
- "PAGE FAULT while accessing address: {:x}{:?}Flags: {:b} Stack: {:x}",
+ "PAGE FAULT while accessing address: 0x{:08x}\nerror code: {:?}(0x{:x})\n{}",
Cr2::read().as_u64(),
error_code,
- stack_frame.cpu_flags,
- stack_frame.stack_pointer.as_u64()
+ error_code.bits(),
+ exception_default!(stack_frame)
);
}
@@ -29,10 +37,9 @@ pub extern "x86-interrupt" fn segment_not_present_handler(
error_code: u64,
) {
panic!(
- "SEGMENT NOT PRESENT: {:?}Flags: {:b} Stack: {:x}",
+ "SEGMENT NOT PRESENT exception\nerror code: 0x{:x}\n{}",
error_code,
- stack_frame.cpu_flags,
- stack_frame.stack_pointer.as_u64()
+ exception_default!(stack_frame)
);
}
@@ -41,8 +48,7 @@ pub extern "x86-interrupt" fn double_fault_handler(
_error_code: u64, // code is always zero
) {
panic!(
- "DOUBLE FAULT Flags: {:b} Stack: {:x}",
- stack_frame.cpu_flags,
- stack_frame.stack_pointer.as_u64()
+ "DOUBLE FAULT\nthis is a fatal exception\n{}",
+ exception_default!(stack_frame)
);
}
diff --git a/kernel/src/io/mod.rs b/kernel/src/io/mod.rs
index 9ac924a..e5dc66f 100644
--- a/kernel/src/io/mod.rs
+++ b/kernel/src/io/mod.rs
@@ -1,3 +1,4 @@
pub mod qemu;
pub mod serial;
pub mod vga_text;
+pub mod panic_screen;
diff --git a/kernel/src/io/panic_screen.rs b/kernel/src/io/panic_screen.rs
new file mode 100644
index 0000000..ce2c118
--- /dev/null
+++ b/kernel/src/io/panic_screen.rs
@@ -0,0 +1,57 @@
+use core::fmt::Write;
+use crate::io::vga_text::{OStream, CharState, Color};
+
+const PANIC_SCREEN_MESSAGE_BUFFER_SIZE: usize = 2048;
+
+struct TextBuffer<'a> {
+ dst: &'a mut [u8],
+ len: usize
+}
+
+impl<'a> TextBuffer<'a> {
+ fn new(dst: &'a mut [u8]) -> Self {
+ Self { dst, len: 0 }
+ }
+ fn get(&'a mut self) -> &'a mut [u8] {
+ &mut self.dst[..self.len]
+ }
+}
+
+impl<'a> core::fmt::Write for TextBuffer<'a> {
+ fn write_str(&mut self, s: &str) -> core::fmt::Result {
+ if s.len() + self.len > self.dst.len() {
+ Err(core::fmt::Error)
+ } else {
+ let s = s.as_bytes();
+ (&mut self.dst[self.len..self.len+s.len()]).clone_from_slice(s);
+ Ok(self.len += s.len())
+ }
+ }
+}
+
+pub fn show(args: Option<&core::fmt::Arguments>) {
+ let mut stderr = OStream::new();
+ stderr.set_state(CharState::from_colors(
+ Color::LightRed,
+ Color::Red,
+ ));
+ stderr.clear();
+ stderr.print(b"uff-os");
+ stderr.set_row(10);
+ stderr.set_state(CharState::from_colors(
+ Color::White,
+ Color::Red,
+ ));
+ stderr.print_centered(b"<kernel panic>");
+ stderr.set_row(14);
+ stderr.set_state(CharState::from_colors(
+ Color::Cyan,
+ Color::Red,
+ ));
+ stderr.set_centered(true);
+ let buffer: &mut [u8] = &mut [b' '; PANIC_SCREEN_MESSAGE_BUFFER_SIZE];
+ let mut tbuffer = TextBuffer::new(buffer);
+ let _ = core::fmt::write(&mut tbuffer, *args.unwrap_or(&format_args!("no panic information obtainable")));
+ stderr.print(tbuffer.get());
+ stderr.set_centered(false);
+}
diff --git a/kernel/src/io/vga_text.rs b/kernel/src/io/vga_text.rs
index 281a40a..277db73 100644
--- a/kernel/src/io/vga_text.rs
+++ b/kernel/src/io/vga_text.rs
@@ -103,7 +103,7 @@ impl OStream {
pub fn put_char(&mut self, c: VgaChar) {
if c.byte == b'\n' {
self.new_line();
- } else if self.pos.0 >= WIDTH - 1 {
+ } else if self.pos.0 >= WIDTH {
self.new_line();
self.put_char(c);
} else {
@@ -158,31 +158,15 @@ impl OStream {
}
pub fn print_centered(&mut self, s: &[u8]) {
- let mut line = &s[..];
- let mut n = 0;
- if s.len() == 0 { return; }
- let slast = s.len() - 1;
- for (i, &b) in s.iter().enumerate() {
- if n >= WIDTH {
- self.set_col(0);
- self.put_bytes(&line[..WIDTH]);
- line = &line[WIDTH..];
- n = 0;
+ let mut line_start = 0;
+ let mut line_len = 0;
+ for line in s.split(|&c| c == b'\n') {
+ if line.is_empty() { self.new_line() }
+ for chunk in line.chunks(WIDTH) {
+ self.set_col((WIDTH - chunk.len()) >> 1);
+ self.put_bytes(chunk);
+ self.new_line()
}
- if b == b'\n' || i == slast {
- if b != b'\n' {
- n += 1
- }
- self.set_col(((WIDTH - n) / 2) as usize);
- self.put_bytes(&line[..n]);
- self.new_line();
- if i == slast {
- return;
- }
- line = &line[(n + 1)..];
- n = 0;
- }
- n += 1;
}
}
}
diff --git a/kernel/src/lib.rs b/kernel/src/lib.rs
index a81520b..59888d1 100644
--- a/kernel/src/lib.rs
+++ b/kernel/src/lib.rs
@@ -25,11 +25,8 @@ pub extern "C" fn _start() -> ! {
test_main();
qemu::exit_qemu(qemu::QemuExitCode::Success);
}
- x86_64::instructions::interrupts::int3();
- let stdout = OStream::new();
- stdout.clear();
- panic!("panic! at the disco");
+ x86_64::instructions::interrupts::int3();
/// TODO: write test
///fn _loop(i: u64) -> u64 {
@@ -50,32 +47,8 @@ pub extern "C" fn _start() -> ! {
#[panic_handler]
#[no_mangle]
pub extern "C" fn panic_handler(info: &core::panic::PanicInfo) -> ! {
- let mut stderr = OStream::new();
- stderr.set_state(vga_text::CharState::from_colors(
- vga_text::Color::LightRed,
- vga_text::Color::Red,
- ));
- stderr.clear();
- stderr.print(b"uff-os");
- stderr.set_row(10);
- stderr.set_state(vga_text::CharState::from_colors(
- vga_text::Color::White,
- vga_text::Color::Red,
- ));
- stderr.print_centered(b"<kernel panic>");
- stderr.set_row(14);
- stderr.set_state(vga_text::CharState::from_colors(
- vga_text::Color::Cyan,
- vga_text::Color::Red,
- ));
- stderr.set_centered(true);
- write!(
- &mut stderr,
- "{:?}",
- info.message()
- .unwrap_or(&format_args!("no panic information obtainable"))
- );
- stderr.set_centered(false);
+ io::panic_screen::show(info.message());
+
if cfg!(test) {
write!(serial::SerialStream::new(), "Testing failed\n").unwrap();
qemu::exit_qemu(qemu::QemuExitCode::Failed);