diff --git a/files.mk b/files.mk index 8d0a3c11..bd9ce197 100644 --- a/files.mk +++ b/files.mk @@ -21,6 +21,7 @@ RUST_SRCS = main.rs \ task.rs \ signal.rs \ queue.rs \ + kinit.rs\ errno.rs \ debug.rs\ $(SYSCALL_SRCS) \ diff --git a/srcs/cli.rs b/srcs/cli.rs index a07aa6e1..5424f804 100644 --- a/srcs/cli.rs +++ b/srcs/cli.rs @@ -8,8 +8,9 @@ use crate::string::{String, ToString}; use crate::syscalls::exit::sys_waitpid; use crate::syscalls::signal::sys_kill; use crate::vec::Vec; -use crate::vga_buffer::{hexdump, screenclear}; -use crate::{io, kprint, kprintln}; +use crate::vga_buffer::screenclear; +use crate::x86::io; +use crate::{kprint, kprintln}; const NB_CMDS: usize = 13; @@ -34,9 +35,8 @@ const KNOWN_CMD: [&str; NB_CMDS] = [ ]; fn kill(command: Vec) { - let mut count: usize = 0; let mut wstatus: i32 = 0; - let mut pid: Pid = 0; + let pid: Pid; if command.len() != 2 { kprintln!("Invalid argument."); @@ -167,13 +167,12 @@ fn hexdump_parser(command: Vec) { return; } - hexdump(args[0] as *const u8, args[1]); + crate::vga_buffer::hexdump(args[0] as *const u8, args[1]); } use crate::keyboard::{KEYMAP, KEYMAP_FR, KEYMAP_US}; fn keymap(command: Vec) { - let mut count: usize = 0; if command.len() != 2 { kprintln!("Invalid number of arguments."); @@ -196,7 +195,7 @@ extern "C" { } fn interrupt(command: Vec) { - let mut arg: usize = 0; + let arg: usize; if command.len() != 2 { kprintln!("Invalid number of arguments."); diff --git a/srcs/debug.rs b/srcs/debug.rs index c989f20a..01235ac2 100644 --- a/srcs/debug.rs +++ b/srcs/debug.rs @@ -18,7 +18,7 @@ impl fmt::Write for DWriter { /// Send to SERIAL_COM2 all bytes from s fn write_str(&mut self, s: &str) -> fmt::Result { for i in s.bytes() { - crate::io::outb(SERIAL_COM2, i); + crate::x86::io::outb(SERIAL_COM2, i); } Ok(()) } diff --git a/srcs/interrupts/mod.rs b/srcs/interrupts/mod.rs index d6e3c21f..653d6453 100644 --- a/srcs/interrupts/mod.rs +++ b/srcs/interrupts/mod.rs @@ -1,48 +1,16 @@ //! Setup interrupts and exception handler +use crate::x86::interrupt::{ + EXCEPTION_SIZE, + IDT_MAX_DESCRIPTORS, + IDT_SIZE, + STR_EXCEPTION +}; use crate::proc::process::Status; -use crate::proc::task::{schedule_task, switch_task, Task}; +use crate::proc::task::{switch_task, Task}; use crate::syscalls::syscall_handler; const GDT_OFFSET_KERNEL_CODE: u16 = 0x08; -const IDT_SIZE: usize = 48; -const IDT_MAX_DESCRIPTORS: usize = 256; - -const EXCEPTION_SIZE: usize = 32; -const STR_EXCEPTION: [&'static str; EXCEPTION_SIZE] = [ - "Divide-by-zero", - "Debug", - "Non-maskable Interrupt", - "Breakpoint", - "Overflow", - "Bound Range Exceeded", - "Invalid Opcode", - "Device Not Available", - "Double Fault", - "Coprocessor Segment Overrun", - "Invalid TSS", - "Segment Not Present", - "Stack-Segment Fault", - "General Protection Fault", - "Page Fault", - "Reserved", - "x87 Floating-Point Exception", - "Alignment Check", - "Machine Check", - "SIMD Floating-Point Exception", - "Virtualization Exception", - "Control Protection Exception", - "Reserved", - "Reserved", - "Reserved", - "Reserved", - "Reserved", - "Reserved", - "Hypervisor Injection Exception", - "VMM Communication Exception", - "Security Exception", - "Reserved" -]; extern "C" { static mut isr_stub_table: [u32; IDT_SIZE]; diff --git a/srcs/keyboard.rs b/srcs/keyboard.rs index 93ddb7f8..6e0a51d7 100644 --- a/srcs/keyboard.rs +++ b/srcs/keyboard.rs @@ -1,7 +1,8 @@ //! Keyboard handler and key mapping use crate::vga_buffer::NB_SCREEN; -use crate::{io, kprint, vga_buffer}; +use crate::x86::io; +use crate::vga_buffer; const PRESSED: usize = 0; const RELEASED: usize = 1; diff --git a/srcs/kinit.rs b/srcs/kinit.rs index 7393e515..ffe14df5 100644 --- a/srcs/kinit.rs +++ b/srcs/kinit.rs @@ -77,7 +77,6 @@ mod string; mod vec; #[macro_use] mod syscalls; -mod io; mod pic; mod proc; mod user; @@ -88,6 +87,7 @@ mod errno; mod sound; mod spin; mod utils; +mod x86; #[macro_use] mod debug; diff --git a/srcs/memory/paging/mod.rs b/srcs/memory/paging/mod.rs index 5a86c28c..df3bb6d8 100644 --- a/srcs/memory/paging/mod.rs +++ b/srcs/memory/paging/mod.rs @@ -39,7 +39,7 @@ pub fn init_paging() { bitmap::physmap_as_mut().get_page().unwrap(); // Use identity mapping to setup kernel page let init_pt_paddr: PhysAddr = pd_paddr + 0x1000; - let mut init_page_tab: &mut PageTable = &mut *(init_pt_paddr as *mut _); + let init_page_tab: &mut PageTable = &mut *(init_pt_paddr as *mut _); init_page_tab .set_entry(768, kernel_pt_paddr | PAGE_WRITABLE | PAGE_PRESENT); refresh_tlb!(); @@ -126,27 +126,5 @@ macro_rules! get_vaddr { }; } -macro_rules! refresh_tlb { - () => { - core::arch::asm!("mov eax, cr3", "mov cr3, eax") - }; -} - -#[allow(unused)] -macro_rules! enable_paging { - ($page_directory:expr) => (core::arch::asm!("mov eax, {p}", - "mov cr3, eax", - "mov eax, cr0", - "or eax, 0x80000001", - "mov cr0, eax", - p = in(reg) (&$page_directory as *const _) as usize);); -} - -#[allow(unused)] -macro_rules! disable_paging { - () => { - core::arch::asm!("mov ebx, cr0", "and ebx, ~(1 << 31)", "mov cr0, ebx") - }; -} - -pub(crate) use {get_paddr, get_vaddr, refresh_tlb}; +pub(crate) use crate::refresh_tlb; +pub(crate) use {get_paddr, get_vaddr}; diff --git a/srcs/pic/mod.rs b/srcs/pic/mod.rs index 685a2eaf..500488c5 100644 --- a/srcs/pic/mod.rs +++ b/srcs/pic/mod.rs @@ -1,6 +1,5 @@ //! Setup Programmable Interrupt Controller - -use crate::io::{inb, io_wait, outb}; +use crate::x86::io::{inb, io_wait, outb}; pub mod handlers; pub mod pit; diff --git a/srcs/pic/pit.rs b/srcs/pic/pit.rs index 749588c8..db075066 100644 --- a/srcs/pic/pit.rs +++ b/srcs/pic/pit.rs @@ -1,5 +1,5 @@ -use crate::io::{inb, outb}; - +use crate::x86::io::{inb, outb}; +use crate::x86::port::PortWriteOnly; // I/O port Usage // 0x40 Channel 0 data port (read/write) // 0x41 Channel 1 data port (read/write) @@ -89,18 +89,22 @@ pub fn set_irq0_in_ms(ms: f32) { } pub fn set_pit(channel: u8, access: u8, mode: u8, data: u16) { - let port: u16 = match channel { - CHANNEL_0 => CHAN0_DATA.into(), - CHANNEL_1 => CHAN1_DATA.into(), - CHANNEL_2 => CHAN2_DATA.into(), + let mut cmd_port: PortWriteOnly = PortWriteOnly::new(MODE_CMD as u16); + + let mut data_port: PortWriteOnly = match channel { + CHANNEL_0 => PortWriteOnly::new(CHAN0_DATA.into()), + CHANNEL_1 => PortWriteOnly::new(CHAN1_DATA.into()), + CHANNEL_2 => PortWriteOnly::new(CHAN2_DATA.into()), _ => panic!("PIT Channel {channel} doesn't exist") }; - // Set cmd mod selected - outb(MODE_CMD as u16, channel | access | mode); + unsafe { + // Set cmd mod selected + cmd_port.write(channel | access | mode); - // Sending data to commands - outb(port, (data & 0xff) as u8); - outb(port, ((data & 0xff00) >> 8) as u8); + // Sending data to commands + data_port.write((data & 0xff) as u8); + data_port.write((data >> 8) as u8); + } } pub fn play_sound(frequency: f32) { diff --git a/srcs/proc/mod.rs b/srcs/proc/mod.rs index fa780340..e1cf29af 100644 --- a/srcs/proc/mod.rs +++ b/srcs/proc/mod.rs @@ -141,6 +141,6 @@ pub fn change_kernel_stack(addr: VirtAddr) { get_paddr!(addr), PAGE_WRITABLE | PAGE_GLOBAL ); - refresh_tlb!(); + crate::refresh_tlb!(); } } diff --git a/srcs/proc/task.rs b/srcs/proc/task.rs index 16d0ad23..f31bbda5 100644 --- a/srcs/proc/task.rs +++ b/srcs/proc/task.rs @@ -74,7 +74,7 @@ impl Task { get_paddr!(MASTER_PROCESS.kernel_stack.offset), PAGE_WRITABLE ); - refresh_tlb!(); + crate::refresh_tlb!(); MASTER_PROCESS.stack = ::init_addr( stack_addr, 0x1000, diff --git a/srcs/sound/mod.rs b/srcs/sound/mod.rs index af7b4b59..5b7bf034 100644 --- a/srcs/sound/mod.rs +++ b/srcs/sound/mod.rs @@ -1,5 +1,5 @@ use crate::main::sleep; -use crate::pic::pit::{play_sound, speaker_off, speaker_on}; +use crate::pic::pit::{speaker_off, speaker_on}; use crate::vec::Vec; mod notes_frequencies; @@ -52,7 +52,7 @@ impl Partition { note_tempo: NoteTempo, note_type: NoteType ) -> &mut Self { - let mut duration: usize = match note_tempo { + let duration: usize = match note_tempo { NoteTempo::WHOLE => self.whole_note_duration, NoteTempo::HALF => self.half_note_duration, NoteTempo::QUARTER => self.quarter_note_duration, @@ -79,7 +79,7 @@ impl Partition { frequencies: (f32, f32, f32), note_tempo: NoteTempo ) { - let mut duration: usize = match note_tempo { + let duration: usize = match note_tempo { NoteTempo::WHOLE => self.whole_note_duration, NoteTempo::HALF => self.half_note_duration, NoteTempo::QUARTER => self.quarter_note_duration, @@ -98,7 +98,7 @@ impl Partition { note_tempo: NoteTempo, div: usize ) { - let mut duration: usize = match note_tempo { + let duration: usize = match note_tempo { NoteTempo::WHOLE => self.whole_note_duration, NoteTempo::HALF => self.half_note_duration, NoteTempo::QUARTER => self.quarter_note_duration, diff --git a/srcs/sound/notes_frequencies.rs b/srcs/sound/notes_frequencies.rs index 8bed2c7c..f7fd29d3 100644 --- a/srcs/sound/notes_frequencies.rs +++ b/srcs/sound/notes_frequencies.rs @@ -1,3 +1,4 @@ +#![allow(non_upper_case_globals)] pub const C2: f32 = 65.41; pub const Cs2: f32 = 69.30; pub const Db2: f32 = Cs2; diff --git a/srcs/sound/overworld.rs b/srcs/sound/overworld.rs index b08f5f4e..8cc90a6a 100644 --- a/srcs/sound/overworld.rs +++ b/srcs/sound/overworld.rs @@ -16,7 +16,7 @@ impl Partition { partition.add_note(G5, NoteTempo::QUARTER, NoteType::BASE); partition.add_note(G4, NoteTempo::QUARTER, NoteType::BASE); - for i in 0..2 { + for _ in 0..2 { partition.add_note(C5, NoteTempo::EIGTH, NoteType::DOTTED); partition.add_note(G4, NoteTempo::EIGTH, NoteType::DOTTED); partition.add_note(E4, NoteTempo::EIGTH, NoteType::BASE); @@ -38,7 +38,7 @@ impl Partition { } // B - for i in 0..2 { + for _ in 0..2 { partition.add_note(Rest, NoteTempo::EIGTH, NoteType::BASE); partition.add_note(G5, NoteTempo::SIXTEENTH, NoteType::BASE); partition.add_note(Gb5, NoteTempo::SIXTEENTH, NoteType::BASE); @@ -138,7 +138,7 @@ impl Partition { partition.add_note(G4, NoteTempo::QUARTER, NoteType::BASE); // A' - for i in 0..2 { + for _ in 0..2 { partition.add_note(C5, NoteTempo::EIGTH, NoteType::DOTTED); partition.add_note(G4, NoteTempo::EIGTH, NoteType::DOTTED); partition.add_note(E4, NoteTempo::EIGTH, NoteType::BASE); @@ -160,7 +160,7 @@ impl Partition { } // D - for i in 0..2 { + for _ in 0..2 { partition.add_note(E5, NoteTempo::SIXTEENTH, NoteType::BASE); partition.add_note(C5, NoteTempo::EIGTH, NoteType::BASE); partition.add_note(G4, NoteTempo::EIGTH, NoteType::DOTTED); diff --git a/srcs/test.rs b/srcs/test.rs index 6fc160d5..0064e48f 100644 --- a/srcs/test.rs +++ b/srcs/test.rs @@ -1,5 +1,6 @@ use crate::vga_buffer::color::Color; -use crate::{io, vga_buffer, KTRACKER}; +use crate::x86::io; +use crate::{vga_buffer, KTRACKER}; #[cfg(test)] #[macro_export] diff --git a/srcs/vga_buffer/cursor.rs b/srcs/vga_buffer/cursor.rs index b36250b2..35d4238b 100644 --- a/srcs/vga_buffer/cursor.rs +++ b/srcs/vga_buffer/cursor.rs @@ -1,5 +1,5 @@ -use crate::io; use crate::vga_buffer::{ColorCode, BUFFER_WIDTH}; +use crate::x86::io; #[derive(Debug, Clone, Copy)] pub struct Cursor { diff --git a/srcs/vga_buffer/mod.rs b/srcs/vga_buffer/mod.rs index 5191c253..8926391b 100644 --- a/srcs/vga_buffer/mod.rs +++ b/srcs/vga_buffer/mod.rs @@ -1,6 +1,7 @@ //! Handler for vga buffer -use crate::{io, Command}; +use crate::x86::io; +use crate::Command; use core::fmt; use core::fmt::Write; use core::panic::PanicInfo; diff --git a/srcs/x86/interrupt.rs b/srcs/x86/interrupt.rs new file mode 100644 index 00000000..2dcf1bd6 --- /dev/null +++ b/srcs/x86/interrupt.rs @@ -0,0 +1,38 @@ +pub const IDT_SIZE: usize = 48; +pub const IDT_MAX_DESCRIPTORS: usize = 256; + +pub const EXCEPTION_SIZE: usize = 32; +pub const STR_EXCEPTION: [&'static str; EXCEPTION_SIZE] = [ + "Divide-by-zero", + "Debug", + "Non-maskable Interrupt", + "Breakpoint", + "Overflow", + "Bound Range Exceeded", + "Invalid Opcode", + "Device Not Available", + "Double Fault", + "Coprocessor Segment Overrun", + "Invalid TSS", + "Segment Not Present", + "Stack-Segment Fault", + "General Protection Fault", + "Page Fault", + "Reserved", + "x87 Floating-Point Exception", + "Alignment Check", + "Machine Check", + "SIMD Floating-Point Exception", + "Virtualization Exception", + "Control Protection Exception", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Hypervisor Injection Exception", + "VMM Communication Exception", + "Security Exception", + "Reserved" +]; diff --git a/srcs/io.rs b/srcs/x86/io.rs similarity index 100% rename from srcs/io.rs rename to srcs/x86/io.rs diff --git a/srcs/x86/mod.rs b/srcs/x86/mod.rs new file mode 100644 index 00000000..374e9f59 --- /dev/null +++ b/srcs/x86/mod.rs @@ -0,0 +1,14 @@ +pub mod interrupt; +pub mod io; +pub mod paging; +pub mod port; + +#[allow(dead_code)] +pub fn io_wait() { + unsafe { + core::arch::asm!("out dx, eax", + in("dx") 0x80, + in("eax") 0, + options(nomem, nostack, preserves_flags)); + } +} diff --git a/srcs/x86/paging.rs b/srcs/x86/paging.rs new file mode 100644 index 00000000..f36e480e --- /dev/null +++ b/srcs/x86/paging.rs @@ -0,0 +1,23 @@ +#[macro_export] +macro_rules! refresh_tlb { + () => { + core::arch::asm!("mov eax, cr3", "mov cr3, eax") + }; +} + +#[macro_export] +macro_rules! enable_paging { + ($page_directory:expr) => (core::arch::asm!("mov eax, {p}", + "mov cr3, eax", + "mov eax, cr0", + "or eax, 0x80000001", + "mov cr0, eax", + p = in(reg) (&$page_directory as *const _) as usize);); +} + +#[macro_export] +macro_rules! disable_paging { + () => { + core::arch::asm!("mov ebx, cr0", "and ebx, ~(1 << 31)", "mov cr0, ebx") + }; +} diff --git a/srcs/x86/port/markers.rs b/srcs/x86/port/markers.rs new file mode 100644 index 00000000..cd21ce75 --- /dev/null +++ b/srcs/x86/port/markers.rs @@ -0,0 +1,17 @@ +/// Marker to allow read access +pub trait PortReadAccess {} +/// Marker to allow write access +pub trait PortWriteAccess {} + +/// Marker structure that allow only read access +pub struct ReadOnlyAccess {} +impl PortReadAccess for ReadOnlyAccess {} + +/// Marker structure that allow only write access +pub struct WriteOnlyAccess {} +impl PortWriteAccess for WriteOnlyAccess {} + +/// Marker structure that allow both read/write access +pub struct ReadWriteAccess {} +impl PortWriteAccess for ReadWriteAccess {} +impl PortReadAccess for ReadWriteAccess {} diff --git a/srcs/x86/port/mod.rs b/srcs/x86/port/mod.rs new file mode 100644 index 00000000..b5ea813d --- /dev/null +++ b/srcs/x86/port/mod.rs @@ -0,0 +1,52 @@ +use core::marker::PhantomData; + +mod markers; +pub use markers::{ + PortReadAccess, + PortWriteAccess, + ReadOnlyAccess, + ReadWriteAccess, + WriteOnlyAccess +}; + +mod ops; +pub use ops::{PortRead, PortWrite}; + +/// Generic structure for a Port type. +/// Generic T: Data type to read/write (e.g: u8,u16,u32) +/// Generic MODE: Structure marker to validate access type (e.g: PortReadAccess) +/// +/// Function depending on the access MODE selected will force the generic MODE to implement the +/// trait corresponding to the correct access +/// e.g: impl for PortGeneric .... +/// If the struct passed as geenric argument implement the correct marker trait +/// implementation will be done +pub struct PortGeneric { + port: u16, + _mode: PhantomData<(T, MODE)> +} + +impl PortGeneric { + pub const fn new(port: u16) -> Self { + Self { port: port, _mode: PhantomData } + } +} + +/// Type aliases for Read/Write accessed port +pub type Port = PortGeneric; +/// Type aliases for Read only accessed port +pub type PortReadOnly = PortGeneric; +/// Type aliases for Write only accessed port +pub type PortWriteOnly = PortGeneric; + +impl PortGeneric { + pub unsafe fn read(&self) -> T { + T::read_from_port(self.port) + } +} + +impl PortGeneric { + pub unsafe fn write(&mut self, value: T) { + T::write_to_port(self.port, value); + } +} diff --git a/srcs/x86/port/ops.rs b/srcs/x86/port/ops.rs new file mode 100644 index 00000000..c2edf358 --- /dev/null +++ b/srcs/x86/port/ops.rs @@ -0,0 +1,66 @@ +pub trait PortRead { + unsafe fn read_from_port(port: u16) -> Self; +} +pub trait PortWrite { + unsafe fn write_to_port(port: u16, value: Self); +} + +impl PortRead for u8 { + unsafe fn read_from_port(port: u16) -> u8 { + let mut value: u8; + core::arch::asm!("in al, dx", + in("dx") port, + out("al") value, + options(nomem, nostack, preserves_flags)); + value + } +} + +impl PortRead for u16 { + unsafe fn read_from_port(port: u16) -> u16 { + let mut value: u16; + core::arch::asm!("in ax, dx", + in("dx") port, + out("ax") value, + options(nomem, nostack, preserves_flags)); + value + } +} + +impl PortRead for u32 { + unsafe fn read_from_port(port: u16) -> u32 { + let mut value: u32; + core::arch::asm!("in eax, dx", + in("dx") port, + out("eax") value, + options(nomem, nostack, preserves_flags)); + value + } +} + +impl PortWrite for u8 { + unsafe fn write_to_port(port: u16, value: u8) { + core::arch::asm!("out dx, al", + in("dx") port, + in("al") value, + options(nomem, nostack, preserves_flags)); + } +} + +impl PortWrite for u16 { + unsafe fn write_to_port(port: u16, value: u16) { + core::arch::asm!("out dx, ax", + in("dx") port, + in("ax") value, + options(nomem, nostack, preserves_flags)); + } +} + +impl PortWrite for u32 { + unsafe fn write_to_port(port: u16, value: u32) { + core::arch::asm!("out dx, eax", + in("dx") port, + in("eax") value, + options(nomem, nostack, preserves_flags)); + } +}