From ae743a778eb16afcbc16edb97aec39484f36a499 Mon Sep 17 00:00:00 2001 From: GZTimeWalker Date: Fri, 13 May 2022 04:23:16 +0800 Subject: [PATCH] wip: why `iretq` jump to 0xfff3 --- .gdbinit | 2 + pkg/app/sh/src/main.rs | 4 ++ pkg/kernel/src/drivers/console.rs | 7 ++- pkg/kernel/src/drivers/input.rs | 8 +++ pkg/kernel/src/drivers/mod.rs | 4 +- pkg/kernel/src/interrupt/handlers.rs | 4 +- pkg/kernel/src/interrupt/syscall/mod.rs | 3 +- pkg/kernel/src/interrupt/syscall/service.rs | 55 +++++++++++---------- pkg/kernel/src/lib.rs | 1 + pkg/kernel/src/main.rs | 16 ++---- pkg/kernel/src/process/manager.rs | 10 +++- pkg/kernel/src/process/mod.rs | 13 ++++- pkg/kernel/src/process/process.rs | 14 ++++-- pkg/kernel/src/tasks/executor.rs | 22 ++++++--- pkg/kernel/src/tasks/mod.rs | 5 +- pkg/kernel/src/utils/regs.rs | 2 + pkg/kernel/src/utils/resource.rs | 10 +++- pkg/lib/src/io.rs | 27 +++++++--- pkg/lib/src/syscall.rs | 3 +- 19 files changed, 138 insertions(+), 72 deletions(-) create mode 100644 .gdbinit diff --git a/.gdbinit b/.gdbinit new file mode 100644 index 0000000..1d678b0 --- /dev/null +++ b/.gdbinit @@ -0,0 +1,2 @@ +file esp/KERNEL.ELF +target remote:1234 diff --git a/pkg/app/sh/src/main.rs b/pkg/app/sh/src/main.rs index 2e7f91b..d5fd269 100644 --- a/pkg/app/sh/src/main.rs +++ b/pkg/app/sh/src/main.rs @@ -11,6 +11,9 @@ use lib::io::stdin; extern crate lib; fn main() { + + sys_list_dir("/"); + let mut root_dir = String::from("/APP/"); loop { @@ -43,6 +46,7 @@ fn main() { } "exec" => { let path = root_dir.clone() + line[1]; + println!("ready to exec {}...", path); let pid = sys_spawn(path.as_str()); if pid == 0 { println!("failed to spawn process: {}#{}", line[1], pid); diff --git a/pkg/kernel/src/drivers/console.rs b/pkg/kernel/src/drivers/console.rs index a7a16ed..925fd53 100644 --- a/pkg/kernel/src/drivers/console.rs +++ b/pkg/kernel/src/drivers/console.rs @@ -121,7 +121,12 @@ impl Console { match c { '\n' => self.next_row(), '\r' => self.x_pos = 0, - '\x08' => backspace(), + '\x08' => { + self.prev_char(); + self.write(" "); + self.prev_char(); + self.prev_char(); + }, _ => self.write_char(c), } } diff --git a/pkg/kernel/src/drivers/input.rs b/pkg/kernel/src/drivers/input.rs index 5b2242d..dfc312d 100644 --- a/pkg/kernel/src/drivers/input.rs +++ b/pkg/kernel/src/drivers/input.rs @@ -15,6 +15,14 @@ pub fn init() { info!("Input Initialized."); } +pub fn push_key(key: DecodedKey) { + if let Some(queue) = get_input_buf() { + if let Err(_) = queue.push(key) { + warn!("Input buffer is full."); + } + } +} + pub fn try_get_key() -> Option { interrupts::without_interrupts(|| { if let Some(key) = get_input_buf_for_sure().pop() { diff --git a/pkg/kernel/src/drivers/mod.rs b/pkg/kernel/src/drivers/mod.rs index fecaf70..9ff92ba 100644 --- a/pkg/kernel/src/drivers/mod.rs +++ b/pkg/kernel/src/drivers/mod.rs @@ -5,6 +5,8 @@ pub mod serial; pub mod console; pub mod display; pub mod keyboard; -// pub mod input; +pub mod input; pub mod filesystem; pub mod ata; + +pub use input::{get_key, push_key}; diff --git a/pkg/kernel/src/interrupt/handlers.rs b/pkg/kernel/src/interrupt/handlers.rs index f8954c2..e19a420 100644 --- a/pkg/kernel/src/interrupt/handlers.rs +++ b/pkg/kernel/src/interrupt/handlers.rs @@ -158,9 +158,7 @@ pub extern "C" fn clock(mut regs: Registers, mut sf: InterruptStackFrame) { as_handler!(clock); pub extern "C" fn syscall(mut regs: Registers, mut sf: InterruptStackFrame) { - x86_64::instructions::interrupts::without_interrupts(|| { - super::syscall::dispatcher(&mut regs, &mut sf); - }); + super::syscall::dispatcher(&mut regs, &mut sf); } as_handler!(syscall); diff --git a/pkg/kernel/src/interrupt/syscall/mod.rs b/pkg/kernel/src/interrupt/syscall/mod.rs index 33f7704..78f23af 100644 --- a/pkg/kernel/src/interrupt/syscall/mod.rs +++ b/pkg/kernel/src/interrupt/syscall/mod.rs @@ -45,7 +45,7 @@ pub fn dispatcher(regs: &mut Registers, sf: &mut InterruptStackFrame) { Syscall::SpawnProcess => regs.set_rax(spawn_process(&args)), Syscall::ExitProcess => exit_process(regs, sf), Syscall::Read => regs.set_rax(sys_read(&args)), - Syscall::Write => sys_write(&args), + Syscall::Write => regs.set_rax(sys_write(&args)), Syscall::Open => {} Syscall::Close => {} Syscall::Stat => list_process(), @@ -56,7 +56,6 @@ pub fn dispatcher(regs: &mut Registers, sf: &mut InterruptStackFrame) { Syscall::Draw => sys_draw(&args), Syscall::None => {} } - // debug!("syscall finished."); } impl SyscallArgs { diff --git a/pkg/kernel/src/interrupt/syscall/service.rs b/pkg/kernel/src/interrupt/syscall/service.rs index 5caf9c1..a5cf9ae 100644 --- a/pkg/kernel/src/interrupt/syscall/service.rs +++ b/pkg/kernel/src/interrupt/syscall/service.rs @@ -1,9 +1,9 @@ use core::alloc::Layout; -use crate::{utils::*, display::get_display_for_sure}; +use crate::utils::Registers; +use crate::{display::get_display_for_sure, utils::*}; use embedded_graphics::prelude::*; use x86_64::structures::idt::InterruptStackFrame; -use crate::utils::Registers; use super::SyscallArgs; @@ -14,14 +14,12 @@ pub fn sys_clock() -> i64 { pub fn sys_draw(args: &SyscallArgs) { let _ = get_display_for_sure().draw_pixel_u32( Point::new(args.arg0 as i32, args.arg1 as i32), - args.arg2 as u32 + args.arg2 as u32, ); } pub fn sys_allocate(args: &SyscallArgs) -> usize { - let layout = unsafe { - (args.arg0 as *const Layout).as_ref().unwrap() - }; + let layout = unsafe { (args.arg0 as *const Layout).as_ref().unwrap() }; trace!("sys_allocate: \n{:#?}", layout); let ptr = crate::allocator::ALLOCATOR .lock() @@ -34,7 +32,7 @@ pub fn sys_allocate(args: &SyscallArgs) -> usize { pub fn sys_deallocate(args: &SyscallArgs) { let ptr = args.arg0 as *mut u8; - let layout = unsafe{ (args.arg1 as *const Layout).as_ref().unwrap() }; + let layout = unsafe { (args.arg1 as *const Layout).as_ref().unwrap() }; unsafe { crate::allocator::ALLOCATOR @@ -45,11 +43,12 @@ pub fn sys_deallocate(args: &SyscallArgs) { } pub fn spawn_process(args: &SyscallArgs) -> usize { - let path = unsafe { + let path = unsafe { core::str::from_utf8_unchecked(core::slice::from_raw_parts( - args.arg1 as *const u8, - args.arg2, - ))}; + args.arg0 as *const u8, + args.arg1, + )) + }; let file = crate::filesystem::try_get_file(path); @@ -71,9 +70,7 @@ pub fn spawn_process(args: &SyscallArgs) -> usize { pub fn sys_read(args: &SyscallArgs) -> usize { let fd = get_handle(args.arg0 as u8); if let Some(res) = fd { - let buf = unsafe { - core::slice::from_raw_parts_mut(args.arg1 as *mut u8, args.arg2) - }; + let buf = unsafe { core::slice::from_raw_parts_mut(args.arg1 as *mut u8, args.arg2) }; if let Ok(size) = res.read(buf) { size } else { @@ -84,15 +81,17 @@ pub fn sys_read(args: &SyscallArgs) -> usize { } } -pub fn sys_write(args: &SyscallArgs) { - let s = unsafe{ core::str::from_utf8_unchecked(core::slice::from_raw_parts( - args.arg1 as *const u8, - args.arg2, - ))}; - match args.arg0 { - 1 => print!("{}", s), - 2 => print_warn!("{}", s), - fd => warn!("SYSCALL: cannot write to fd: {}", fd), +pub fn sys_write(args: &SyscallArgs) -> usize { + let fd = get_handle(args.arg0 as u8); + if let Some(res) = fd { + let buf = unsafe { core::slice::from_raw_parts_mut(args.arg1 as *mut u8, args.arg2) }; + if let Ok(size) = res.write(buf) { + size + } else { + 0 + } + } else { + 0 } } @@ -105,10 +104,12 @@ pub fn list_process() { } pub fn list_dir(args: &SyscallArgs) { - let root = unsafe { core::str::from_utf8_unchecked(core::slice::from_raw_parts( - args.arg0 as *const u8, - args.arg1, - )) }; + let root = unsafe { + core::str::from_utf8_unchecked(core::slice::from_raw_parts( + args.arg0 as *const u8, + args.arg1, + )) + }; crate::filesystem::ls(root); } diff --git a/pkg/kernel/src/lib.rs b/pkg/kernel/src/lib.rs index 1e868fb..5c89688 100644 --- a/pkg/kernel/src/lib.rs +++ b/pkg/kernel/src/lib.rs @@ -51,6 +51,7 @@ pub fn init(boot_info: &'static BootInfo) { allocator::init(); // init heap allocator process::init(); // init process manager keyboard::init(); // init keyboard + input::init(); // init input ata::init(); // init ata filesystem::init(); // init filesystem diff --git a/pkg/kernel/src/main.rs b/pkg/kernel/src/main.rs index 6127588..cbb77a8 100644 --- a/pkg/kernel/src/main.rs +++ b/pkg/kernel/src/main.rs @@ -11,18 +11,12 @@ boot::entry_point!(kernal_main); pub fn kernal_main(boot_info: &'static boot::BootInfo) -> ! { ggos::init(boot_info); - // let sh_file = ggos::filesystem::try_get_file("/APP/SH").unwrap(); - // let pid = ggos::process::spawn(&sh_file).unwrap(); + let mut executor = Executor::new(); - // while ggos::process::still_alive(pid) { - // unsafe { - // core::arch::asm!("hlt"); - // } - // } + let sh_file = ggos::filesystem::try_get_file("/APP/SH").unwrap(); + let pid = ggos::process::spawn(&sh_file).unwrap(); - let mut executor = Executor::new(); - executor.spawn(Task::new(get_key())); - executor.run(); + executor.run(pid); - // ggos::shutdown(boot_info); + ggos::shutdown(boot_info); } diff --git a/pkg/kernel/src/process/manager.rs b/pkg/kernel/src/process/manager.rs index 2648663..3d065c3 100644 --- a/pkg/kernel/src/process/manager.rs +++ b/pkg/kernel/src/process/manager.rs @@ -4,6 +4,7 @@ use alloc::format; use alloc::vec::Vec; use x86_64::structures::idt::InterruptStackFrame; use x86_64::VirtAddr; +use x86_64::structures::paging::PhysFrame; use xmas_elf::ElfFile; once_mutex!(pub PROCESS_MANAGER: ProcessManager); @@ -83,6 +84,11 @@ impl ProcessManager { } } + fn get_kernel_page_table(&self) -> PhysFrame { + let proc = self.processes.get(0).unwrap(); + proc.page_table_addr() + } + pub fn spawn( &mut self, elf: &ElfFile, @@ -94,6 +100,7 @@ impl ProcessManager { &mut *crate::memory::get_frame_alloc_for_sure(), name, parent, + self.get_kernel_page_table(), proc_data, ); p.pause(); @@ -102,7 +109,7 @@ impl ProcessManager { VirtAddr::new_truncate(STACK_TOP), ); p.init_elf(elf); - info!("Spawn process: {}#{}", p.name(), p.pid()); + // info!("Spawn process: {}#{}", p.name(), p.pid()); // info!("Spawn process:\n\n{:?}\n", p); let pid = p.pid(); self.processes.push(p); @@ -121,6 +128,7 @@ impl ProcessManager { &mut *crate::memory::get_frame_alloc_for_sure(), name, parent, + self.get_kernel_page_table(), proc_data, ); p.pause(); diff --git a/pkg/kernel/src/process/mod.rs b/pkg/kernel/src/process/mod.rs index a76a6a0..384f04c 100644 --- a/pkg/kernel/src/process/mod.rs +++ b/pkg/kernel/src/process/mod.rs @@ -13,7 +13,10 @@ pub use scheduler::*; use crate::{filesystem::get_volume, Registers, Resource}; use alloc::string::String; -use x86_64::structures::{idt::InterruptStackFrame, paging::FrameAllocator}; +use x86_64::{ + registers::control::Cr3, + structures::{idt::InterruptStackFrame, paging::FrameAllocator}, +}; use self::manager::init_PROCESS_MANAGER; @@ -56,7 +59,13 @@ impl From for u16 { pub fn init() { let mut alloc = crate::memory::get_frame_alloc_for_sure(); // kernel process - let mut kproc = Process::new(&mut *alloc, String::from("kernel"), ProcessId(0), None); + let mut kproc = Process::new( + &mut *alloc, + String::from("kernel"), + ProcessId(0), + Cr3::read().0, + None, + ); kproc.resume(); kproc.set_page_table_with_cr3(); init_PROCESS_MANAGER(ProcessManager::new(kproc)); diff --git a/pkg/kernel/src/process/process.rs b/pkg/kernel/src/process/process.rs index ea33361..91d3ede 100644 --- a/pkg/kernel/src/process/process.rs +++ b/pkg/kernel/src/process/process.rs @@ -78,6 +78,10 @@ impl Process { self.page_table_addr = Cr3::read(); } + pub fn page_table_addr(&self) -> PhysFrame { + self.page_table_addr.0 + } + pub fn is_running(&self) -> bool { self.status == ProgramStatus::Running } @@ -120,18 +124,20 @@ impl Process { frame_alloc: &mut BootInfoFrameAllocator, name: String, parent: ProcessId, + page_table_source: PhysFrame, proc_data: Option, ) -> Self { + let name = name.to_ascii_lowercase(); // 1. alloc a page table for process let page_table_addr = frame_alloc .allocate_frame() .expect("Cannot alloc page table for new process."); - trace!("Alloc page table for {}: {:?}", name, page_table_addr); + debug!("Alloc page table for {}: {:?}", name, page_table_addr); // 2. copy current page table to new page table unsafe { copy_nonoverlapping::( - Cr3::read().0.start_address().as_u64() as *mut PageTable, + page_table_source.start_address().as_u64() as *mut PageTable, page_table_addr.start_address().as_u64() as *mut PageTable, 1, ); @@ -230,8 +236,8 @@ impl core::fmt::Display for Process { fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result { write!( f, - "#{:3} | {:10} | {}", - self.pid, self.name, self.ticks_passed + " #{:-3}| {:10} | {}", + u16::from(self.pid), self.name, self.ticks_passed )?; Ok(()) } diff --git a/pkg/kernel/src/tasks/executor.rs b/pkg/kernel/src/tasks/executor.rs index 8f7a0e6..d46ca19 100644 --- a/pkg/kernel/src/tasks/executor.rs +++ b/pkg/kernel/src/tasks/executor.rs @@ -1,7 +1,11 @@ +use crate::process; + use super::{Task, TaskId}; use alloc::{collections::BTreeMap, sync::Arc, task::Wake}; use core::task::{Context, Poll, Waker}; +use core::future::Future; use crossbeam_queue::ArrayQueue; +use crate::process::ProcessId; pub struct Executor { tasks: BTreeMap, @@ -18,18 +22,24 @@ impl Executor { } } - pub fn spawn(&mut self, task: Task) { + pub fn spawn(&mut self, task: impl Future + 'static) { + let task = Task::new(task); let task_id = task.id; if self.tasks.insert(task.id, task).is_some() { - panic!("task with same ID already in tasks"); + panic!("Task with same ID already in tasks"); } - self.task_queue.push(task_id).expect("queue full"); + self.task_queue.push(task_id).expect("Task queue is full"); } - pub fn run(&mut self) -> ! { + /// only return when init process is not alive + pub fn run(&mut self, init: ProcessId) { loop { self.run_ready_tasks(); - self.sleep_if_idle(); + if process::still_alive(init) { + self.sleep_if_idle(); + } else { + break; + } } } @@ -80,7 +90,7 @@ impl TaskWaker { } fn wake_task(&self) { - self.task_queue.push(self.task_id).expect("task_queue full"); + self.task_queue.push(self.task_id).expect("Task queue is full"); } } diff --git a/pkg/kernel/src/tasks/mod.rs b/pkg/kernel/src/tasks/mod.rs index d0a860b..47dc432 100644 --- a/pkg/kernel/src/tasks/mod.rs +++ b/pkg/kernel/src/tasks/mod.rs @@ -7,9 +7,10 @@ use core::{ }; pub mod executor; -pub mod input; -pub use input::{get_key, push_key}; +// pub mod input; +// pub use input::{get_key, push_key}; + pub use executor::Executor; pub struct Task { id: TaskId, diff --git a/pkg/kernel/src/utils/regs.rs b/pkg/kernel/src/utils/regs.rs index 86fab4d..d7355a1 100644 --- a/pkg/kernel/src/utils/regs.rs +++ b/pkg/kernel/src/utils/regs.rs @@ -86,6 +86,7 @@ macro_rules! as_handler { pub extern "x86-interrupt" fn [<$fn _handler>](_sf: InterruptStackFrame) { unsafe { core::arch::asm!(" + cli push rbp push rax push rbx @@ -117,6 +118,7 @@ macro_rules! as_handler { pop rbx pop rax pop rbp + sti iretq", sym $fn, options(noreturn)); } diff --git a/pkg/kernel/src/utils/resource.rs b/pkg/kernel/src/utils/resource.rs index c3d8fca..4e20f82 100644 --- a/pkg/kernel/src/utils/resource.rs +++ b/pkg/kernel/src/utils/resource.rs @@ -1,7 +1,8 @@ use alloc::string::String; use fs::{Device, File, Random}; +use pc_keyboard::DecodedKey; -use crate::filesystem::{get_volume, StdIO}; +use crate::{filesystem::{get_volume, StdIO}, input::try_get_key}; #[derive(Debug, Clone)] pub enum Resource { @@ -21,7 +22,12 @@ impl Resource { Ok(0) } else { // TODO: get key async - Ok(0) + if let Some(DecodedKey::Unicode(k)) = try_get_key() { + let s = k.encode_utf8(buf); + Ok(s.len()) + } else { + Ok(0) + } } } _ => Err(()), diff --git a/pkg/lib/src/io.rs b/pkg/lib/src/io.rs index a2faa14..b44bf69 100644 --- a/pkg/lib/src/io.rs +++ b/pkg/lib/src/io.rs @@ -8,7 +8,7 @@ pub struct Stderr; impl Stdin { fn new() -> Self { - Self {} + Self } pub fn read_char(&self) -> Option { @@ -24,11 +24,22 @@ impl Stdin { pub fn read_line(&self) -> String { let mut string = String::new(); loop { - if let Some(bytes) = self.read_char() { - if bytes == '\n' { - break; - } else { - string.push(bytes); + if let Some(k) = self.read_char() { + match k { + '\n' => { + stdout().write("\n"); + break; + }, + '\x08' => { + if !string.is_empty() { + stdout().write("\x08"); + string.pop(); + } + } + c => { + print!("{}", k); + string.push(c); + } } } } @@ -38,7 +49,7 @@ impl Stdin { impl Stdout { fn new() -> Self { - Self {} + Self } pub fn write(&self, s: &str) { @@ -48,7 +59,7 @@ impl Stdout { impl Stderr { fn new() -> Self { - Self {} + Self } pub fn write(&self, s: &str) { diff --git a/pkg/lib/src/syscall.rs b/pkg/lib/src/syscall.rs index b3eb737..ddf0864 100644 --- a/pkg/lib/src/syscall.rs +++ b/pkg/lib/src/syscall.rs @@ -1,4 +1,4 @@ -use crate::{Syscall, println}; +use crate::Syscall; use chrono::naive::*; pub fn sys_draw(x: i32, y: i32, color: u32) -> usize { @@ -16,7 +16,6 @@ pub fn sys_write(fd: u64, buf: &[u8]) -> Option { pub fn sys_read(fd: u64, buf: &mut [u8]) -> Option { let ret = syscall!(Syscall::Read, fd, buf.as_ptr() as u64, buf.len() as u64) as isize; - println!("{}: {:?}", ret, buf); if ret.is_negative() { None } else {