From 105df1bcd6812e589bfb5f25eaf3613684b442fb Mon Sep 17 00:00:00 2001 From: Erin Date: Tue, 14 Jun 2022 17:27:30 +0200 Subject: [PATCH] Implemented task spawning - Using `pc-keyboard` instead of custom one as it sometimes caused double-faults on keypress --- Cargo.lock | 7 +++ ableos/Cargo.toml | 3 +- ableos/src/arch/x86_64/interrupts.rs | 76 ++++++++----------------- ableos/src/arch/x86_64/task_switcher.rs | 18 +++++- ableos/src/kmain.rs | 6 +- ableos/src/scheduler.rs | 18 +++++- 6 files changed, 70 insertions(+), 58 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index fa237f1..ea855cd 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -44,6 +44,7 @@ dependencies = [ "log", "logos", "pc-beeper", + "pc-keyboard", "pic8259", "picorand", "pretty-hex", @@ -608,6 +609,12 @@ dependencies = [ "x86_64", ] +[[package]] +name = "pc-keyboard" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c6f2d937e3b8d63449b01401e2bae4041bc9dd1129c2e3e0d239407cf6635ac" + [[package]] name = "pic8259" version = "0.10.2" diff --git a/ableos/Cargo.toml b/ableos/Cargo.toml index 19951fe..db9a1aa 100644 --- a/ableos/Cargo.toml +++ b/ableos/Cargo.toml @@ -54,6 +54,7 @@ libwasm = {git="https://git.ablecorp.us:443/able/libwasm.git"} axel = { git = "https://git.ablecorp.us/able/aos_userland" } versioning = { git = "https://git.ablecorp.us/able/aos_userland" } embedded-graphics="*" +pc-keyboard = "0.5" @@ -133,4 +134,4 @@ volatile = "0.2.6" x86_64 = "*" pc-beeper = {git = "https://github.com/AbleOS/pc-beeper"} vga = "*" -acpi = "4.1.0" \ No newline at end of file +acpi = "4.1.0" diff --git a/ableos/src/arch/x86_64/interrupts.rs b/ableos/src/arch/x86_64/interrupts.rs index d4b947f..d66ea7d 100644 --- a/ableos/src/arch/x86_64/interrupts.rs +++ b/ableos/src/arch/x86_64/interrupts.rs @@ -94,66 +94,40 @@ extern "x86-interrupt" fn timer_interrupt_handler(_stack_frame: InterruptStackFr } extern "x86-interrupt" fn keyboard_interrupt_handler(_stack_frame: InterruptStackFrame) { - use crate::keyboard::{ - CustomLayout, CustomScancodeSet, DecodedKey, DecodedKeyKind, HandleControl, KeyCode, - Keyboard, + use pc_keyboard::{ + layouts::Us104Key, DecodedKey, HandleControl, KeyCode, Keyboard, ScancodeSet1, }; use spin::Mutex; use x86_64::instructions::port::Port; - static KEYBOARD: Lazy>> = Lazy::new(|| { - Mutex::new(Keyboard::new( - CustomLayout::new_us104key(), - CustomScancodeSet::default(), - HandleControl::Ignore, - )) - }); + static KEYBOARD: Lazy>> = + Lazy::new(|| Mutex::new(Keyboard::new(Us104Key, ScancodeSet1, HandleControl::Ignore))); let mut keyboard = KEYBOARD.lock(); - let mut port = Port::new(0x60); - 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 { - kind: DecodedKeyKind::Unicode, - value: character, - } => { - match character { - // Backspace - 8 => { - WRITER.lock().backspace(); - KEYBUFF.lock().push(8_u8 as _); - // print!(" "); - // WRITER.lock().backspace(); - } - - 0x5E => KERNEL_STATE.lock().shutdown(), - - _ => { - let mut buff = KEYBUFF.lock(); - - buff.push(character as u8 as char); - - print!("{}", char::try_from(character).unwrap()); - } - } + if let Ok(Some(key)) = keyboard + .add_byte(unsafe { Port::new(0x60).read() }) + .map(|x| x.and_then(|ev| keyboard.process_keyevent(ev))) + { + match key { + DecodedKey::Unicode(chr) => match chr { + // Backspace + '\u{8}' => { + WRITER.lock().backspace(); + KEYBUFF.lock().push(8.into()); } - DecodedKey { - kind: DecodedKeyKind::RawKey, - value: key, - } => match KeyCode::from(key) { - KeyCode::AltLeft => {} - - KeyCode::AltRight => {} - _ => { - print!("{:?}", KeyCode::from(key)) - } - }, - // Register a keyboard interrupt handler for the given scancode. - } + '^' => KERNEL_STATE.lock().shutdown(), + chr => { + KEYBUFF.lock().push(chr); + print!("{chr}"); + } + }, + DecodedKey::RawKey(key) => match KeyCode::from(key) { + KeyCode::AltLeft | KeyCode::AltRight => (), + kc => print!("{kc:?}"), + }, } } + unsafe { PICS.lock() .notify_end_of_interrupt(InterruptIndex::Keyboard.as_u8()); diff --git a/ableos/src/arch/x86_64/task_switcher.rs b/ableos/src/arch/x86_64/task_switcher.rs index 001ac39..eb0ea9d 100644 --- a/ableos/src/arch/x86_64/task_switcher.rs +++ b/ableos/src/arch/x86_64/task_switcher.rs @@ -78,6 +78,22 @@ pub unsafe extern "C" fn switch_to_next() -> ! { in(reg) sp, options(noreturn), ), - Task::Spawn(_) => todo!("task spawning"), + Task::Spawn { + function, + stack_start, + } => asm!( + "add rsp, 160", // Move above saved registries + "mov [rsp], {ip}", // Set task's instruction pointer + "mov [rsp + 24], {sp}", // Set task's stack pointer + + // Signalise the end of the interrupt and return + "mov al, 32", + "out 20h, al", + "iretq", + + ip = in(reg) function, + sp = in(reg) stack_start, + options(noreturn), + ), } } diff --git a/ableos/src/kmain.rs b/ableos/src/kmain.rs index d8e304d..47d86e0 100644 --- a/ableos/src/kmain.rs +++ b/ableos/src/kmain.rs @@ -1,6 +1,7 @@ #![allow(clippy::empty_loop)] use crate::arch::drivers::sysinfo::master; +use crate::scheduler::SCHEDULER; use crate::{ arch::{init, sloop}, relib::network::socket::{SimpleSock, Socket}, @@ -24,8 +25,9 @@ pub fn kernel_main() -> ! { log::set_max_level(log::LevelFilter::Off); } - // start_facepalm(); - scratchpad(); + x86_64::instructions::interrupts::without_interrupts(|| { + SCHEDULER.lock().enqueue_spawn(scratchpad); + }); sloop() } diff --git a/ableos/src/scheduler.rs b/ableos/src/scheduler.rs index 3b657de..00b9371 100644 --- a/ableos/src/scheduler.rs +++ b/ableos/src/scheduler.rs @@ -3,9 +3,12 @@ use spin::{Lazy, Mutex}; pub static SCHEDULER: Lazy> = Lazy::new(|| Mutex::new(Scheduler::default())); +/// Task's stack size (in kiB) +const STACK_SIZE: usize = 512; + pub enum Task { Suspended(u64), - Spawn(fn()), + Spawn { function: fn(), stack_start: usize }, } #[derive(Default)] @@ -14,8 +17,17 @@ pub struct Scheduler { } impl Scheduler { - pub fn enqueue_spawn(&mut self, f: fn()) { - self.task_queue.push_back(Task::Spawn(f)); + pub fn enqueue_spawn(&mut self, function: fn()) { + self.task_queue.push_back(Task::Spawn { + function, + stack_start: unsafe { + let size = STACK_SIZE * 1024; + alloc::alloc::alloc( + alloc::alloc::Layout::from_size_align(size, 1).expect("invalid layout"), + ) + .add(size - 1) as _ + }, + }); } pub fn enqueue_suspended(&mut self, sp: u64) {