From e48c3fc680e1ffd328d1e610a58ee24077a26fc6 Mon Sep 17 00:00:00 2001 From: Jack Halford Date: Thu, 31 May 2018 18:32:52 +0200 Subject: [PATCH] Does it compile? no. Do I know what Im doing? maybe. Am I making progress? Yes. --- kernel-rs/.gdbinit | 2 - kernel-rs/mk/qemu.mk | 34 ++++++---- kernel-rs/src/arch/x86/boot.asm | 1 + kernel-rs/src/arch/x86/device/mod.rs | 2 +- kernel-rs/src/arch/x86/gdt.rs | 35 +++++++--- kernel-rs/src/arch/x86/interrupt/exception.rs | 5 +- kernel-rs/src/arch/x86/mod.rs | 45 ++++++++++--- kernel-rs/src/lib.rs | 14 ++-- kernel-rs/src/process/fifo.rs | 27 ++++++++ kernel-rs/src/process/mod.rs | 64 +++++++++++++++++++ kernel-rs/src/vga/mod.rs | 10 +-- kernel-rs/x86 | 2 +- 12 files changed, 192 insertions(+), 49 deletions(-) delete mode 100644 kernel-rs/.gdbinit create mode 100644 kernel-rs/src/process/fifo.rs create mode 100644 kernel-rs/src/process/mod.rs diff --git a/kernel-rs/.gdbinit b/kernel-rs/.gdbinit deleted file mode 100644 index 77d679cf..00000000 --- a/kernel-rs/.gdbinit +++ /dev/null @@ -1,2 +0,0 @@ -set arch i386 -file build/bluesnow-x86.bin diff --git a/kernel-rs/mk/qemu.mk b/kernel-rs/mk/qemu.mk index db0f170c..c99cce58 100644 --- a/kernel-rs/mk/qemu.mk +++ b/kernel-rs/mk/qemu.mk @@ -1,27 +1,35 @@ ifeq ($(shell whoami), jack) - PORT := 4242 - PORTG := 4244 + PORT_MONIT := 4242 + PORT_GDB := 4244 else - PORT := 4342 - PORTG := 4344 + PORT_MONIT := 4342 + PORT_GDB := 4344 endif QEMU := qemu-system-i386\ - -gdb tcp::$(PORTG)\ + -cdrom build/bluesnow-x86.iso\ -S\ -enable-kvm\ - -monitor telnet:127.0.0.1:$(PORT),server,nowait\ -curses\ - -cdrom build/bluesnow-x86.iso + -gdb tcp::$(PORT_GDB)\ + -monitor telnet:127.0.0.1:$(PORT_MONIT),server,nowait +qemu: + $(QEMU) -MONITOR := sleep 0.5;\ - telnet 127.0.0.1 $(PORT);\ +GDB := gdb -q\ + -symbols "$(kernel)" \ + -ex "target remote :$(PORT_GDB)"\ + -ex "set arch i386" +gdb: + $(GDB) + +MONITOR := telnet 127.0.0.1 $(PORT_MONIT);\ kill \`ps -x | grep \"[g]db -q\" | cut -d \ -f 1 \`;\ kill \`ps -x | grep \"[g]db -q\" | cut -d \ -f 2 \` -GDB := gdb -q\ - -ex \"target remote :$(PORTG)\" +monitor: + telnet 127.0.0.1 $(PORT_MONIT) -qemu: +#not using this anymore +william: @tmux info >&- || { echo -e "\033[38;5;16mPlease run inside a tmux session\033[0m" ; exit 1; } @tmux new-window 'tmux split-window -h "$(MONITOR)"; tmux split-window -fv "$(GDB)"; tmux select-pane -t 1; tmux resize-pane -x 80 -y 25; $(QEMU)' - diff --git a/kernel-rs/src/arch/x86/boot.asm b/kernel-rs/src/arch/x86/boot.asm index 045dc35a..892fc549 100644 --- a/kernel-rs/src/arch/x86/boot.asm +++ b/kernel-rs/src/arch/x86/boot.asm @@ -4,6 +4,7 @@ extern x86_start section .text bits 32 start: + ; our stack, located in bss, linker.ld puts bss at the end of the binary mov esp, stack_top diff --git a/kernel-rs/src/arch/x86/device/mod.rs b/kernel-rs/src/arch/x86/device/mod.rs index 1a0a08a9..be0549aa 100644 --- a/kernel-rs/src/arch/x86/device/mod.rs +++ b/kernel-rs/src/arch/x86/device/mod.rs @@ -5,5 +5,5 @@ pub mod cpu; pub unsafe fn init(active_table: &mut ActivePageTable) { pic::init(); - local_apic::init(active_table); + // local_apic::init(active_table); } diff --git a/kernel-rs/src/arch/x86/gdt.rs b/kernel-rs/src/arch/x86/gdt.rs index cdfc540d..5510b81f 100644 --- a/kernel-rs/src/arch/x86/gdt.rs +++ b/kernel-rs/src/arch/x86/gdt.rs @@ -8,28 +8,40 @@ use x86::*; pub static mut GDT: gdt::Gdt = gdt::Gdt::new(); pub static mut TSS: tss::TaskStateSegment = tss::TaskStateSegment::new(); +pub static mut TASK_TSS: tss::TaskStateSegment = tss::TaskStateSegment::new(); -pub static GDT_KERNEL_CODE: u16 = 1; -pub static GDT_KERNEL_DATA: u16 = 2; -pub static GDT_USER_CODE: u16 = 3; -pub static GDT_USER_DATA: u16 = 4; -// tss takes 2 spots; -pub static GDT_TSS: u16 = 5; +pub static GDT_KERNEL_CODE: SegmentSelector = SegmentSelector::new(1, Ring0); +pub static GDT_KERNEL_DATA: SegmentSelector = SegmentSelector::new(2, Ring0); +pub static GDT_USER_CODE: SegmentSelector = SegmentSelector::new(3, Ring3); +pub static GDT_USER_DATA: SegmentSelector = SegmentSelector::new(4, Ring3); +pub static GDT_TSS: SegmentSelector = SegmentSelector::new(5, Ring3); +pub static GDT_TASK_TSS: SegmentSelector = SegmentSelector::new(7, Ring3); pub unsafe fn init() { - TSS.ss0 = gdt::SegmentSelector::new(GDT_KERNEL_CODE, PrivilegeLevel::Ring0).0; - asm!("mov %esp, $0" : "=r" (TSS.esp0)); - // the following *order* is important let kcode_selector = GDT.add_entry(gdt::Descriptor::kernel_code_segment()); let kdata_selector = GDT.add_entry(gdt::Descriptor::kernel_data_segment()); let ucode_selector = GDT.add_entry(gdt::Descriptor::user_code_segment()); let udata_selector = GDT.add_entry(gdt::Descriptor::user_data_segment()); + //I read that the tss should be twice as long //fuck knows why... + TSS.ss0 = GDT_KERNEL_CODE.0; + asm!("mov %esp, $0" : "=r" (TSS.esp0)); let tss_selector = GDT.add_entry(gdt::Descriptor::tss_segment(&TSS)); GDT.add_entry(gdt::Descriptor(0)); + TASK_TSS.eip = self::test_task as *const () as u32; + let task_tss_selector = GDT.add_entry(gdt::Descriptor::tss_segment(&TASK_TSS)); + GDT.add_entry(gdt::Descriptor(0)); + + assert_eq!(kcode_selector, GDT_KERNEL_CODE); + assert_eq!(kdata_selector, GDT_KERNEL_DATA); + assert_eq!(ucode_selector, GDT_USER_CODE); + assert_eq!(udata_selector, GDT_USER_DATA); + assert_eq!(tss_selector, GDT_TSS); + assert_eq!(task_tss_selector, GDT_TASK_TSS); + // println!( // "tr({:#x}):\n {:#?}", // tss_selector.0, @@ -45,3 +57,8 @@ pub unsafe fn init() { load_tss(tss_selector); // unreachable!(); } + +pub fn test_task() { + println!("inside test task omg we did it !!!"); + flush!(); +} diff --git a/kernel-rs/src/arch/x86/interrupt/exception.rs b/kernel-rs/src/arch/x86/interrupt/exception.rs index d9b034d2..4f86fca8 100644 --- a/kernel-rs/src/arch/x86/interrupt/exception.rs +++ b/kernel-rs/src/arch/x86/interrupt/exception.rs @@ -56,17 +56,20 @@ exception_err!(invalid_tss, {}); exception_err!(segment_not_present, {}); exception_err!(stack_segment, {}); exception_err!(general_protection, { - panic!("general protection fault (#GP) can not recover"); + panic!("cannot recover from #GP"); }); pub extern "x86-interrupt" fn page_fault( stack_frame: &mut ExceptionStackFrame, code: PageFaultErrorCode, ) { + use x86::registers::control::Cr2; println!("Exception: page_fault"); println!("Error code: {:?}", code); + println!("PFLA: {:?}", Cr2::read()); println!("{:#?}", stack_frame); flush!(); + panic!("cannot recover from #PF") } exception!(x87_fpu, {}); diff --git a/kernel-rs/src/arch/x86/mod.rs b/kernel-rs/src/arch/x86/mod.rs index 4355d810..d22592ca 100644 --- a/kernel-rs/src/arch/x86/mod.rs +++ b/kernel-rs/src/arch/x86/mod.rs @@ -45,6 +45,12 @@ pub unsafe extern "C" fn x86_rust_start(multiboot_info_addr: usize) { // set up heap ::allocator::init(&mut active_table); + // set up user stack + use x86::structures::paging::*; + // for page in ::USER_STACK_RANGE { + // active_table.map(page, PageTableFlags::WRITABLE); + // } + // set up pic & apic device::init(&mut active_table); @@ -52,7 +58,12 @@ pub unsafe extern "C" fn x86_rust_start(multiboot_info_addr: usize) { ::kmain(); } -pub unsafe fn usermode(ip: u32, sp: u32, arg: u32) -> ! { +pub unsafe fn switch(ip: u32) -> ! { + asm!("push $0; ret" :: "r"(ip) :: "volatile", "intel"); + unreachable!(); +} + +pub unsafe fn usermode(ip: u32, mut sp: u32, arg: u32) -> ! { use x86::structures::gdt::{Descriptor, SegmentSelector}; use x86::instructions::segmentation::*; use x86::PrivilegeLevel::{Ring0, Ring3}; @@ -62,12 +73,26 @@ pub unsafe fn usermode(ip: u32, sp: u32, arg: u32) -> ! { // println!("sp: {:#x}", sp); // println!("ip: {:#x}", ip); - let udata_selector = SegmentSelector::new(gdt::GDT_USER_DATA, Ring0); - let ucode_selector = SegmentSelector::new(gdt::GDT_USER_CODE, Ring3); - load_ds(udata_selector); - load_es(udata_selector); - load_fs(udata_selector); - load_gs(udata_selector); + // load_ds(udata_selector); + // asm!("mov $0, %ds" :: "r"(gdt::GDT_USER_DATA << 3 | 3)); + + // loop {} + + // load_es(udata_selector); + // load_fs(udata_selector); + // load_gs(udata_selector); + + use x86::registers::flags; + flags::set_flags(flags::Flags::NT); + + asm!("mov %esp, $0" : "=r" (sp)); + + println!("{:#x}", gdt::GDT_KERNEL_DATA.0); + println!("{:#x}", sp); + println!("{:#x}", 1 << 9); + println!("{:#x}", gdt::GDT_KERNEL_CODE.0); + println!("{:#x}", ip); + flush!(); asm!(" push $0; \ @@ -76,15 +101,17 @@ pub unsafe fn usermode(ip: u32, sp: u32, arg: u32) -> ! { push $3; \ push $4" : //no output - : "r"(udata_selector), + : "r"(gdt::GDT_USER_DATA.0), "r"(sp), "r"(1 << 9) // interrupt enable flag - "r"(ucode_selector), + "r"(gdt::GDT_USER_CODE.0), "r"(ip) : //no clobbers : "intel", "volatile" ); + // loop {} + asm!("iret"); unreachable!(); diff --git a/kernel-rs/src/lib.rs b/kernel-rs/src/lib.rs index b9686b90..5d4bbfee 100644 --- a/kernel-rs/src/lib.rs +++ b/kernel-rs/src/lib.rs @@ -45,6 +45,8 @@ pub mod memory; /// arch specific entry points pub mod arch; pub use arch::x86::consts::*; +/// process scheduling +pub mod process; /// kernel entry point. arch module is responsible for /// calling this once the core has loaded @@ -69,24 +71,20 @@ pub fn kmain() -> ! { // println!("flags: {:?}", x86::registers::flags::flags()); // flush!(); - let sp = (::USER_STACK_OFFSET + ::USER_STACK_SIZE).as_u32(); + // let sp = (::USER_STACK_OFFSET + ::USER_STACK_SIZE).as_u32(); // let sp: u32; // unsafe { // asm!("mov %ebp, $0" : "=r" (sp)); // } - let ip = self::init as *const () as u32; // unsafe { // arch::x86::usermode(ip, sp, 0); // } // unreachable!() - loop {} -} -pub fn init() { - println!("inside init function!!!!!"); - flush!(); - loop {} + process::ploop(); + + unreachable!(); } #[lang = "eh_personality"] diff --git a/kernel-rs/src/process/fifo.rs b/kernel-rs/src/process/fifo.rs new file mode 100644 index 00000000..c0889fb3 --- /dev/null +++ b/kernel-rs/src/process/fifo.rs @@ -0,0 +1,27 @@ +use spin::Mutex; +use alloc::VecDeque; + +use super::*; + +pub struct Fifo { + list: VecDeque, +} + +impl Fifo { + pub fn new() -> Fifo { + Fifo { + list: VecDeque::new(), + } + } +} + +impl Scheduler for Fifo { + fn add_process(&mut self, ip: u32) { + let p = Process::new(ip); + self.list.push_back(p); + } + + fn next(&mut self) -> Option { + self.list.pop_front() + } +} diff --git a/kernel-rs/src/process/mod.rs b/kernel-rs/src/process/mod.rs new file mode 100644 index 00000000..5f7ffd14 --- /dev/null +++ b/kernel-rs/src/process/mod.rs @@ -0,0 +1,64 @@ +mod fifo; + +lazy_static! { + static ref SCHEDULER: fifo::Fifo = fifo::Fifo::new(); +} + +// lazy_static! { +// static ref SCHEDULER: self::Scheduler = self::Scheduler { +// list: Mutex::new(VecDeque::new()) +// }; +// } + +#[derive(Debug)] +pub struct Process { + // this is eip right now + // this will be an elf blob later + ip: u32, +} + +impl Process { + pub fn new(ip: u32) -> Process { + Process { ip } + } + + pub unsafe fn execute(&mut self) { + asm!("push $0; ret" :: "r"(self.ip) :: "volatile", "intel"); + } +} + +pub trait Scheduler { + fn add_process(&mut self, ip: u32); + fn next(&mut self) -> Option; +} + +pub fn ploop() { + let ip = self::init as *const () as u32; + unsafe { + SCHEDULER.add_process(ip); + } + loop { + if let Some(mut p) = unsafe { SCHEDULER.next() } { + print!("{:?}", p); + unsafe { + p.execute(); + } + } + } +} + +pub fn fork() -> i32 { + let ip; + unsafe { + asm!("" : "={eip}"(ip) ::: "volatile"); + SCHEDULER.add_process(ip); + } + 0 +} + +pub fn init() -> ! { + let i = self::fork(); + println!("inside fork_print() function!!!!!, fork={}", i); + flush!(); + loop {} +} diff --git a/kernel-rs/src/vga/mod.rs b/kernel-rs/src/vga/mod.rs index 27be530c..8a3cfbef 100644 --- a/kernel-rs/src/vga/mod.rs +++ b/kernel-rs/src/vga/mod.rs @@ -32,9 +32,9 @@ macro_rules! flush { macro_rules! set_color { () => (unsafe { $crate::vga::VGA.color_code = - $crate::vga::ColorCode::new($crate::vga::Color::White, $crate::vga::Color::Black)} ); + $crate::vga::ColorCode::new($crate::vga::Color::Black, $crate::vga::Color::Yellow)} ); ($fg:ident) => (unsafe { $crate::vga::VGA.color_code = - $crate::vga::ColorCode::new($crate::vga::Color::$fg, $crate::vga::Color::Black)} ); + $crate::vga::ColorCode::new($crate::vga::Color::$fg, $crate::vga::Color::Yellow)} ); ($fg:ident, $bg:ident) => (unsafe { $crate::vga::VGA.color_code = $crate::vga::ColorCode::new($crate::vga::Color::$fg, $crate::vga::Color::$bg)} ); } @@ -63,7 +63,7 @@ impl Writer { pub const fn new() -> Writer { Writer { buffer_pos: 0, - color_code: ColorCode::new(Color::White, Color::Black), + color_code: ColorCode::new(Color::Black, Color::Yellow), buffer: [0; BUFFER_ROWS * BUFFER_COLS], command: [b'\0'; 10], command_len: 0, @@ -100,7 +100,7 @@ impl Writer { b'\n' => { self.write_byte(b'\n'); if let Err(msg) = console::exec(&self) { - set_color!(Red, Black); + set_color!(Red, Yellow); println!("Something wrong: {}", msg); set_color!(); } @@ -180,7 +180,7 @@ impl Writer { for col in (0..BUFFER_COLS / 2).map(|x| x * 2) { self.buffer[((BUFFER_ROWS - 1) * BUFFER_COLS) + (col)] = b' '; self.buffer[((BUFFER_ROWS - 1) * BUFFER_COLS) + (col + 1)] = - ColorCode::new(Color::White, Color::Black).0; + ColorCode::new(Color::Black, Color::Yellow).0; } self.buffer_pos = (BUFFER_ROWS - 1) * BUFFER_COLS; diff --git a/kernel-rs/x86 b/kernel-rs/x86 index 3a6ff64c..d81e8a36 160000 --- a/kernel-rs/x86 +++ b/kernel-rs/x86 @@ -1 +1 @@ -Subproject commit 3a6ff64c5fb9a4bdeb8b6b4c83328278c551dbad +Subproject commit d81e8a3690f3cd2dc64f0d6ebabceeb8e5583c97