From 0bbbf653f89b5f39235c7c51e3a43aefcae1277d Mon Sep 17 00:00:00 2001 From: zxq5 Date: Sat, 22 Feb 2025 15:41:41 +0000 Subject: [PATCH] setup GDT & fixed a deadlock --- Cargo.lock | 7 ++++ kernel/Cargo.toml | 1 + kernel/src/arch/x86_64/gdt.rs | 53 +++++++++++++++++++++++++++- kernel/src/arch/x86_64/interrupts.rs | 37 +++++++++++++++++-- kernel/src/lib.rs | 1 + 5 files changed, 95 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index e7b8c2c..c575ba9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -38,6 +38,7 @@ dependencies = [ "lib_framebuffer", "lib_serial", "limine", + "pc-keyboard", "pic8259", "spin", "x86_64", @@ -105,6 +106,12 @@ dependencies = [ "scopeguard", ] +[[package]] +name = "pc-keyboard" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0ca629cbb3f0d5b699c338f0129ff78c9bfd7ea8b1258ad529bff490dc8ed5a" + [[package]] name = "pic8259" version = "0.11.0" diff --git a/kernel/Cargo.toml b/kernel/Cargo.toml index 4759c3f..91a92ca 100644 --- a/kernel/Cargo.toml +++ b/kernel/Cargo.toml @@ -11,6 +11,7 @@ lib_ascii = { path = "../lib/lib_ascii" } x86_64 = "0.15.2" spin = "0.9.8" pic8259 = "0.11.0" +pc-keyboard = "0.8.0" [build-dependencies] cc = "1.2.14" diff --git a/kernel/src/arch/x86_64/gdt.rs b/kernel/src/arch/x86_64/gdt.rs index bf4c036..8d9bad4 100644 --- a/kernel/src/arch/x86_64/gdt.rs +++ b/kernel/src/arch/x86_64/gdt.rs @@ -1,4 +1,12 @@ -use x86_64::{structures::tss::TaskStateSegment, VirtAddr}; +use x86_64::{ + instructions::tables::load_tss, + registers::segmentation::{Segment, CS, DS, ES, SS}, + structures::{ + gdt::{Descriptor, GlobalDescriptorTable, SegmentSelector}, + tss::TaskStateSegment, + }, + VirtAddr, +}; use spin::Lazy; @@ -16,3 +24,46 @@ static TSS: Lazy = Lazy::new(|| { }; tss }); + +static GDT: Lazy<(GlobalDescriptorTable, Selectors)> = Lazy::new(|| { + let mut gdt = GlobalDescriptorTable::new(); + let code_selector = gdt.append(Descriptor::kernel_code_segment()); + let data_selector = gdt.append(Descriptor::kernel_data_segment()); + + let user_code_selector = gdt.append(Descriptor::user_code_segment()); + let user_data_selector = gdt.append(Descriptor::user_data_segment()); + + let tss_selector = gdt.append(Descriptor::tss_segment(&TSS)); + + ( + gdt, + Selectors { + code_selector, + data_selector, + user_code_selector, + user_data_selector, + tss_selector, + }, + ) +}); + +struct Selectors { + code_selector: SegmentSelector, + data_selector: SegmentSelector, + user_code_selector: SegmentSelector, + user_data_selector: SegmentSelector, + tss_selector: SegmentSelector, +} + +pub fn init() { + GDT.0.load(); + + unsafe { + CS::set_reg(GDT.1.code_selector); + load_tss(GDT.1.tss_selector); + + DS::set_reg(self::GDT.1.data_selector); + ES::set_reg(self::GDT.1.data_selector); + SS::set_reg(self::GDT.1.data_selector); + } +} diff --git a/kernel/src/arch/x86_64/interrupts.rs b/kernel/src/arch/x86_64/interrupts.rs index 160cf20..c2c7251 100644 --- a/kernel/src/arch/x86_64/interrupts.rs +++ b/kernel/src/arch/x86_64/interrupts.rs @@ -1,4 +1,4 @@ -use lib_ascii::println_log; +use lib_ascii::{print, println_log}; use lib_serial::serial_println; use x86_64::instructions::port::Port; use x86_64::structures::idt::{InterruptDescriptorTable, InterruptStackFrame}; @@ -6,10 +6,18 @@ use x86_64::structures::idt::{InterruptDescriptorTable, InterruptStackFrame}; use pic8259::ChainedPics; use spin::{Lazy, Mutex}; +use super::gdt; + static IDT: Lazy = Lazy::new(|| { let mut idt = InterruptDescriptorTable::new(); idt.breakpoint.set_handler_fn(breakpoint_handler); - idt.double_fault.set_handler_fn(double_fault_handler); + + unsafe { + idt.double_fault + .set_handler_fn(double_fault_handler) + .set_stack_index(gdt::DOUBLE_FAULT_1ST_INDEX); + } + idt.general_protection_fault .set_handler_fn(general_protection_fault_handler); @@ -71,8 +79,31 @@ extern "x86-interrupt" fn double_fault_handler( } extern "x86-interrupt" fn keyboard_interrupt_handler(_stack_frame: InterruptStackFrame) { + use pc_keyboard::{layouts, DecodedKey, HandleControl, Keyboard, ScancodeSet1}; + use spin::Mutex; + use x86_64::instructions::port::Port; + + static KEYBOARD: Lazy>> = Lazy::new(|| { + Mutex::new(Keyboard::new( + ScancodeSet1::new(), + layouts::Us104Key, + HandleControl::Ignore, + )) + }); + + let mut keyboard = KEYBOARD.lock(); let mut port = Port::new(0x60); - let _scancode: u8 = unsafe { port.read() }; + + let scancode: u8 = unsafe { port.read() }; + if let Ok(Some(key_event)) = keyboard.add_byte(scancode) { + if let Some(key) = keyboard.process_keyevent(key_event) { + match key { + DecodedKey::Unicode(character) => print!("{}", character), + DecodedKey::RawKey(key) => print!("{:?}", key), + } + } + } + unsafe { PICS.lock() .notify_end_of_interrupt(InterruptIndex::Keyboard.as_u8()); diff --git a/kernel/src/lib.rs b/kernel/src/lib.rs index c36854e..aa16295 100644 --- a/kernel/src/lib.rs +++ b/kernel/src/lib.rs @@ -53,6 +53,7 @@ pub fn boot() -> Result<(), &'static str> { } lib_serial::init()?; + arch::x86_64::gdt::init(); arch::x86_64::interrupts::init_idt(); x86_64::instructions::interrupts::enable();