fixed the interrupts issue
This commit is contained in:
+3
-1
@@ -20,7 +20,9 @@ pub extern "C" fn kmain() -> ! {
|
||||
GoofyAhhOS::init();
|
||||
|
||||
println!("Hello from GoofyAhhOS!");
|
||||
serial_println!("SERIAL OUT ACHIEVED :check:");
|
||||
// serial_println!("SERIAL OUT ACHIEVED :check:");
|
||||
|
||||
loop {}
|
||||
|
||||
loop {
|
||||
let input: &str = serial_read();
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
// use core::arch::x86_64::__cpuid;
|
||||
|
||||
|
||||
|
||||
// static IA32_APIC_BASE_MSR: u32 = 0x1b;
|
||||
// static IA32_APIC_BASE_MSR_BSP: u32 = 0x100;
|
||||
// static IA32_APIC_BASE_MSR_ENABLE: u32 = 0x800;
|
||||
|
||||
// fn check_apic() -> bool {
|
||||
// let edx = unsafe {
|
||||
// __cpuid(1,)
|
||||
// }.edx;
|
||||
// return edx & CPU_ID_FEAT_EDX_APIC != 0
|
||||
// }
|
||||
@@ -1,5 +1,5 @@
|
||||
use x86_64::{
|
||||
instructions::tables::load_tss, registers::segmentation::{Segment, CS}, structures::{
|
||||
instructions::tables::load_tss, registers::segmentation::{Segment, CS, DS, ES, SS}, structures::{
|
||||
gdt::{
|
||||
Descriptor, GlobalDescriptorTable, SegmentSelector
|
||||
},
|
||||
@@ -17,7 +17,7 @@ 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 * 5;
|
||||
const STACK_SIZE: usize = 4096 * 8;
|
||||
static mut STACK: [u8; STACK_SIZE] = [0; STACK_SIZE];
|
||||
|
||||
let stack_start = VirtAddr::from_ptr(unsafe { &STACK });
|
||||
@@ -30,16 +30,36 @@ lazy_static! {
|
||||
|
||||
lazy_static! {
|
||||
static ref GDT: (GlobalDescriptorTable, Selectors) = {
|
||||
x86_64::instructions::interrupts::disable();
|
||||
let mut gdt = GlobalDescriptorTable::new();
|
||||
// Kernel code segment
|
||||
let code_selector = gdt.append(Descriptor::kernel_code_segment());
|
||||
// Kernel data segment (needed for proper interrupt handling)
|
||||
let data_selector = gdt.append(Descriptor::kernel_data_segment());
|
||||
// User segments (even if not used, helps with some hardware)
|
||||
let user_data_selector = gdt.append(Descriptor::user_data_segment());
|
||||
let user_code_selector = gdt.append(Descriptor::user_code_segment());
|
||||
// TSS segment for interrupt stack switching
|
||||
let tss_selector = gdt.append(Descriptor::tss_segment(&TSS));
|
||||
(gdt, Selectors { code_selector, tss_selector })
|
||||
(
|
||||
gdt,
|
||||
Selectors {
|
||||
code_selector,
|
||||
data_selector,
|
||||
// user_code_selector,
|
||||
// user_data_selector,
|
||||
tss_selector,
|
||||
}
|
||||
)
|
||||
};
|
||||
}
|
||||
|
||||
struct Selectors {
|
||||
code_selector: SegmentSelector,
|
||||
tss_selector: SegmentSelector
|
||||
data_selector: SegmentSelector,
|
||||
// user_code_selector: SegmentSelector,
|
||||
// user_data_selector: SegmentSelector,
|
||||
tss_selector: SegmentSelector,
|
||||
}
|
||||
|
||||
pub fn init() {
|
||||
@@ -47,8 +67,13 @@ pub fn init() {
|
||||
println_log!("Loaded GDT...");
|
||||
|
||||
unsafe {
|
||||
// Load the segment selectors
|
||||
CS::set_reg(GDT.1.code_selector);
|
||||
load_tss(GDT.1.tss_selector);
|
||||
|
||||
// // Set up data segments
|
||||
// DS::set_reg(GDT.1.data_selector);
|
||||
// ES::set_reg(GDT.1.data_selector);
|
||||
SS::set_reg(GDT.1.data_selector);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -2,7 +2,7 @@ use core::arch::asm;
|
||||
|
||||
use lazy_static::lazy_static;
|
||||
use spin::lazy;
|
||||
use x86_64::structures::idt::{InterruptDescriptorTable, InterruptStackFrame};
|
||||
use x86_64::{instructions::{self, hlt, interrupts}, structures::idt::{InterruptDescriptorTable, InterruptStackFrame, PageFaultErrorCode}};
|
||||
|
||||
use crate::{println_log, serial_println, sys::kernel::cpu::gdt};
|
||||
|
||||
@@ -23,6 +23,7 @@ pub static PICS: spin::Mutex<ChainedPics> = spin::Mutex::new(
|
||||
#[repr(u8)]
|
||||
pub enum InterruptIndex {
|
||||
Timer = PIC_1_OFFSET,
|
||||
Keyboard,
|
||||
}
|
||||
|
||||
impl InterruptIndex {
|
||||
@@ -39,6 +40,9 @@ lazy_static! {
|
||||
static ref IDT: InterruptDescriptorTable = {
|
||||
let mut idt = InterruptDescriptorTable::new();
|
||||
idt.breakpoint.set_handler_fn(breakpoint_handler);
|
||||
idt.page_fault.set_handler_fn(page_fault_handler);
|
||||
idt.general_protection_fault.set_handler_fn(general_protection_fault_handler);
|
||||
|
||||
|
||||
unsafe {
|
||||
idt.double_fault.set_handler_fn(double_fault_handler)
|
||||
@@ -46,6 +50,10 @@ lazy_static! {
|
||||
}
|
||||
|
||||
idt[InterruptIndex::Timer.as_u8()].set_handler_fn(timer_interrupt_handler);
|
||||
|
||||
idt[InterruptIndex::Keyboard.as_u8()]
|
||||
.set_handler_fn(keyboard_interrupt_handler);
|
||||
|
||||
idt
|
||||
};
|
||||
}
|
||||
@@ -56,33 +64,112 @@ pub fn init() {
|
||||
|
||||
unsafe {
|
||||
PICS.lock().initialize();
|
||||
PICS.lock().write_masks(0xfc, 0xff);
|
||||
// println_log!("PIC initialized with masks: {:02x}, {:02x}",
|
||||
// PICS.lock().read_masks()[0],
|
||||
// PICS.lock().read_masks()[1]
|
||||
// );
|
||||
println_log!("weird");
|
||||
}
|
||||
|
||||
x86_64::instructions::interrupts::enable();
|
||||
unsafe { asm!("sti"); }
|
||||
println_log!("Enabled interrupts...");
|
||||
}
|
||||
|
||||
extern "x86-interrupt" fn timer_interrupt_handler(stack_frame: InterruptStackFrame) {
|
||||
serial_println!("clock");
|
||||
println_log!("clock");
|
||||
without(|| {
|
||||
println_log!("Timer interrupt!");
|
||||
});
|
||||
|
||||
unsafe {
|
||||
PICS.lock().notify_end_of_interrupt(InterruptIndex::Timer.as_u8());
|
||||
}
|
||||
}
|
||||
|
||||
extern "x86-interrupt" fn general_protection_fault_handler(
|
||||
stack_frame: InterruptStackFrame,
|
||||
error_code: u64,
|
||||
) {
|
||||
without(|| {
|
||||
// hlt();
|
||||
|
||||
let rsp: u64;
|
||||
unsafe {
|
||||
asm!("mov {}, rsp", out(reg) rsp);
|
||||
}
|
||||
serial_println!("EXCEPTION: GENERAL PROTECTION FAULT");
|
||||
serial_println!("Error Code: {:#x}", error_code);
|
||||
serial_println!("RSP: {:#x}", rsp);
|
||||
serial_println!("Instruction Pointer: {:#x}", stack_frame.instruction_pointer.as_u64());
|
||||
serial_println!("Stack Pointer: {:#x}", stack_frame.stack_pointer.as_u64());
|
||||
serial_println!("CPU Flags: {:#x}", stack_frame.cpu_flags.bits());
|
||||
serial_println!("Code Segment: {:?}", stack_frame.code_segment);
|
||||
serial_println!("Stack Segment: {:?}", stack_frame.stack_segment);
|
||||
});
|
||||
|
||||
panic!("EXCEPTION: GENERAL PROTECTION FAULT");
|
||||
}
|
||||
|
||||
extern "x86-interrupt" fn breakpoint_handler(stack_frame: InterruptStackFrame) {
|
||||
println_log!("EXCEPTION: BREAKPOINT\n{:#?}", stack_frame);
|
||||
serial_println!("EXCEPTION: BREAKPOINT\n{:#?}", stack_frame);
|
||||
without(|| {
|
||||
println_log!("EXCEPTION: BREAKPOINT\n{:#?}", stack_frame);
|
||||
serial_println!("EXCEPTION: BREAKPOINT\n{:#?}", stack_frame);
|
||||
});
|
||||
|
||||
loop {}
|
||||
}
|
||||
|
||||
extern "x86-interrupt" fn double_fault_handler(stack_frame: InterruptStackFrame, _error_code: u64) -> ! {
|
||||
serial_println!("EXCEPTION: DOUBLE FAULT\n{:#?}", stack_frame);
|
||||
without(|| {
|
||||
serial_println!("EXCEPTION: DOUBLE FAULT\n{:#?}", stack_frame);
|
||||
});
|
||||
panic!("EXCEPTION: DOUBLE FAULT\n{:#?}", stack_frame)
|
||||
}
|
||||
|
||||
pub fn disable(func: impl Fn()) {
|
||||
x86_64::instructions::interrupts::disable();
|
||||
func();
|
||||
x86_64::instructions::interrupts::enable();
|
||||
extern "x86-interrupt" fn page_fault_handler(
|
||||
stack_frame: InterruptStackFrame,
|
||||
error_code: PageFaultErrorCode,
|
||||
) {
|
||||
use x86_64::registers::control::Cr2;
|
||||
|
||||
without(|| {
|
||||
serial_println!("EXCEPTION: PAGE FAULT");
|
||||
serial_println!("Accessed Address: {:?}", Cr2::read());
|
||||
serial_println!("Error Code: {:?}", error_code);
|
||||
serial_println!("Stack Frame: {:#?}", stack_frame);
|
||||
});
|
||||
|
||||
panic!("EXCEPTION: PAGE FAULT");
|
||||
}
|
||||
|
||||
pub fn without(func: impl Fn()) {
|
||||
if are_enabled() {
|
||||
unsafe { asm!("cli"); }
|
||||
func();
|
||||
unsafe { asm!("sti"); }
|
||||
} else {
|
||||
func();
|
||||
}
|
||||
}
|
||||
|
||||
pub fn are_enabled() -> bool {
|
||||
let flags: u64;
|
||||
unsafe {
|
||||
asm!("pushfq; pop {}", out(reg) flags);
|
||||
}
|
||||
flags & (1 << 9) != 0 // Bit 9 is the Interrupt Flag (IF)
|
||||
}
|
||||
|
||||
extern "x86-interrupt" fn keyboard_interrupt_handler(_stack_frame: InterruptStackFrame) {
|
||||
use x86_64::instructions::port::Port;
|
||||
|
||||
let mut port = Port::new(0x60);
|
||||
|
||||
serial_println!("KEYBOARD INTERRUPT");
|
||||
|
||||
let scancode: u8 = unsafe { port.read() };
|
||||
|
||||
unsafe {
|
||||
PICS.lock().notify_end_of_interrupt(InterruptIndex::Keyboard.as_u8());
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
pub mod interrupts;
|
||||
pub mod gdt;
|
||||
pub mod apic;
|
||||
|
||||
mod pics;
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ use core::fmt;
|
||||
use lazy_static::lazy_static;
|
||||
use spin::Mutex;
|
||||
|
||||
use crate::sys::kernel::cpu::interrupts;
|
||||
use crate::sys::kernel::cpu::x86_64::interrupts;
|
||||
|
||||
use super::{font::FONT, render::FRAMEBUFFER_WRITER};
|
||||
|
||||
@@ -125,7 +125,7 @@ impl core::fmt::Write for TextWriter {
|
||||
fn write(args: fmt::Arguments, fg_color: u32, bg_color: u32) {
|
||||
use core::fmt::Write;
|
||||
|
||||
interrupts::disable(|| {
|
||||
interrupts::without(|| {
|
||||
let mut writer = TEXT_WRITER.lock();
|
||||
writer.set_colour((fg_color, bg_color));
|
||||
writer.write_fmt(args).unwrap();
|
||||
@@ -146,13 +146,15 @@ pub fn _log(args: fmt::Arguments) {
|
||||
}
|
||||
|
||||
pub fn clear_screen() {
|
||||
let mut writer = TEXT_WRITER.lock();
|
||||
writer.text_line = 0;
|
||||
writer.text_col = 0;
|
||||
|
||||
if let Some(writer) = FRAMEBUFFER_WRITER.lock().as_mut() {
|
||||
writer.clear();
|
||||
}
|
||||
interrupts::without(|| {
|
||||
let mut writer = TEXT_WRITER.lock();
|
||||
writer.text_line = 0;
|
||||
writer.text_col = 0;
|
||||
|
||||
if let Some(writer) = FRAMEBUFFER_WRITER.lock().as_mut() {
|
||||
writer.clear();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
|
||||
@@ -1,19 +1,19 @@
|
||||
use core::fmt;
|
||||
use core::{fmt, sync::atomic::{AtomicUsize, Ordering}};
|
||||
use spin::Mutex;
|
||||
use lazy_static::lazy_static;
|
||||
|
||||
use crate::sys::kernel::cpu::{inb, outb};
|
||||
use crate::sys::kernel::cpu::x86_64::interrupts;
|
||||
|
||||
static PORT: u16 = 0x3f8;
|
||||
static mut BUFFER: [u8; 256] = [0; 256];
|
||||
static BUFFER_LEN: AtomicUsize = AtomicUsize::new(0);
|
||||
|
||||
lazy_static!{
|
||||
static ref SERIAL_WRITER: Mutex<SerialWriter> = Mutex::new(SerialWriter::new());
|
||||
}
|
||||
|
||||
struct SerialWriter {
|
||||
buffer_len: usize
|
||||
}
|
||||
struct SerialWriter;
|
||||
|
||||
impl fmt::Write for SerialWriter {
|
||||
fn write_str(&mut self, s: &str) -> fmt::Result {
|
||||
@@ -45,9 +45,7 @@ impl SerialWriter {
|
||||
outb(PORT + 4, 0x0F);
|
||||
}
|
||||
|
||||
SerialWriter {
|
||||
buffer_len: 0
|
||||
}
|
||||
SerialWriter
|
||||
}
|
||||
|
||||
// returnstrue if there is new data on the serial port
|
||||
@@ -68,15 +66,15 @@ impl SerialWriter {
|
||||
pub fn read_str_to_buffer(&mut self) { unsafe {
|
||||
while !self.serial_recieved() {};
|
||||
|
||||
self.buffer_len = 0;
|
||||
BUFFER_LEN.store(0, Ordering::SeqCst);
|
||||
|
||||
while self.serial_recieved() && self.buffer_len < 256 {
|
||||
while self.serial_recieved() && BUFFER_LEN.load(Ordering::SeqCst) < 256 {
|
||||
let c = inb(PORT + 0);
|
||||
BUFFER[self.buffer_len] = c;
|
||||
BUFFER[BUFFER_LEN.load(Ordering::SeqCst)] = c;
|
||||
if c == b'\n' {
|
||||
break;
|
||||
}
|
||||
self.buffer_len += 1;
|
||||
BUFFER_LEN.fetch_add(1, Ordering::SeqCst);
|
||||
}
|
||||
}}
|
||||
|
||||
@@ -89,19 +87,31 @@ impl SerialWriter {
|
||||
pub fn _serial_write(args: fmt::Arguments) {
|
||||
use core::fmt::Write;
|
||||
|
||||
SERIAL_WRITER.lock().write_fmt(args).unwrap();
|
||||
interrupts::without(|| {
|
||||
SERIAL_WRITER.lock().write_fmt(args).unwrap();
|
||||
})
|
||||
}
|
||||
|
||||
#[macro_use]
|
||||
#[macro_export]
|
||||
macro_rules! serial_println {
|
||||
() => ($crate::serial_print!("\n"));
|
||||
($($arg:tt)*) => ($crate::serial_print!("{}\n", format_args!($($arg)*)));
|
||||
}
|
||||
|
||||
pub fn serial_read() -> &'static str {
|
||||
SERIAL_WRITER.lock().read_str_to_buffer();
|
||||
let i = SERIAL_WRITER.lock().buffer_len;
|
||||
|
||||
if i == 0 {
|
||||
return "";
|
||||
}
|
||||
serial_println!("getting value!");
|
||||
|
||||
unsafe {
|
||||
return core::str::from_utf8(&BUFFER[..i - 1]).unwrap();
|
||||
interrupts::without(|| {
|
||||
SERIAL_WRITER.lock().read_str_to_buffer();
|
||||
});
|
||||
|
||||
let i = BUFFER_LEN.load(Ordering::SeqCst);
|
||||
|
||||
return unsafe {
|
||||
if i != 0 {
|
||||
core::str::from_utf8(&BUFFER[..i - 1]).unwrap()
|
||||
} else { "" }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -110,8 +120,3 @@ macro_rules! serial_print {
|
||||
($($arg:tt)*) => ($crate::_serial_write(format_args!($($arg)*)));
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! serial_println {
|
||||
() => ($crate::serial_print!("\n"));
|
||||
($($arg:tt)*) => ($crate::serial_print!("{}\n", format_args!($($arg)*)));
|
||||
}
|
||||
@@ -16,7 +16,7 @@
|
||||
"code-model": "kernel",
|
||||
"pre-link-args": {
|
||||
"ld.lld": [
|
||||
"--script=/home/fantasypvp/Projects/OSDev/GoofyAhhOS/kernel/linker.ld",
|
||||
"--script=kernel/linker.ld",
|
||||
"-nostdlib",
|
||||
"--no-dynamic-linker",
|
||||
"-static",
|
||||
|
||||
+4
-1
@@ -127,7 +127,7 @@ if [ $is_test -eq 1 ]; then
|
||||
serial_flags="-serial stdio"
|
||||
else
|
||||
test_flags=""
|
||||
# serial_flags="-serial tcp:127.0.0.1:1234,server,nowait"
|
||||
# serial_flags="-serial tcp:127.0.0.1:1234,server -monitor telnet:127.0.0.1:1235,server"
|
||||
serial_flags="-serial stdio"
|
||||
fi
|
||||
|
||||
@@ -158,6 +158,8 @@ check_test_res() {
|
||||
}
|
||||
|
||||
|
||||
kvm_flag=""
|
||||
|
||||
trap 'check_test_res "tests completed"' ERR
|
||||
|
||||
cd "$project_root"
|
||||
@@ -171,3 +173,4 @@ qemu-system-x86_64 -M q35 \
|
||||
${test_flags} \
|
||||
${debug_flags} \
|
||||
${QEMU_FLAGS:-}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user