From 842a2b23fe36b4d4111d983d9687ed8a3b451c98 Mon Sep 17 00:00:00 2001 From: Arthur Beck Date: Sat, 5 Apr 2025 17:32:51 -0500 Subject: [PATCH] Removed proc macros(for now) as kernel items are pretty much useless, added untested interrupts stuff --- kernel/Cargo.toml | 1 - kernel/aphrodite_proc_macros/Cargo.toml | 14 -- kernel/check | 4 +- kernel/config.aphro.example | 1 + kernel/src/kernel/arch/example_impl/mod.rs | 6 - kernel/src/kernel/arch/x86/gdt.rs | 4 + kernel/src/kernel/arch/x86/interrupt_impls.rs | 36 ++++ kernel/src/kernel/arch/x86/interrupts.rs | 15 +- kernel/src/kernel/arch/x86/memory.rs | 180 ------------------ kernel/src/kernel/arch/x86/mod.rs | 74 +++++-- kernel/src/kernel/arch/x86/paging.rs | 4 - kernel/src/kernel/cfg.rs | 2 +- kernel/src/kernel/indep_boot_entry.rs | 7 +- kernel/src/kernel/mem.rs | 6 +- kernel/src/kernel/mod.rs | 1 + kernel/src/proc_macros/mod.rs | 62 ------ 16 files changed, 108 insertions(+), 309 deletions(-) delete mode 100644 kernel/aphrodite_proc_macros/Cargo.toml create mode 100644 kernel/src/kernel/arch/x86/interrupt_impls.rs delete mode 100644 kernel/src/kernel/arch/x86/memory.rs delete mode 100644 kernel/src/proc_macros/mod.rs diff --git a/kernel/Cargo.toml b/kernel/Cargo.toml index d8f16cc..e3b8bba 100644 --- a/kernel/Cargo.toml +++ b/kernel/Cargo.toml @@ -5,7 +5,6 @@ edition = "2024" [dependencies] paste = "1.0.15" -aphrodite_proc_macros = { path = "./aphrodite_proc_macros"} [profile.release] opt-level = "z" diff --git a/kernel/aphrodite_proc_macros/Cargo.toml b/kernel/aphrodite_proc_macros/Cargo.toml deleted file mode 100644 index 219725f..0000000 --- a/kernel/aphrodite_proc_macros/Cargo.toml +++ /dev/null @@ -1,14 +0,0 @@ -[package] -name = "aphrodite_proc_macros" -version = "0.1.0" -edition = "2024" - -[lib] -proc-macro = true -path = "../src/proc_macros/mod.rs" - -[dependencies] -quote = "1.0.38" -syn = { version = "2.0.98", features = ["full"] } -aphrodite_common = { path = "../aphrodite_common" } -proc-macro2 = "1.0.93" diff --git a/kernel/check b/kernel/check index 9c4d6ae..19276e6 100755 --- a/kernel/check +++ b/kernel/check @@ -19,7 +19,7 @@ real_check=false if [[ "$HAVE_GETOPT" = "true" ]]; then - LONGOPTS=real_check + LONGOPTS=real_check,real-check OPTIONS=c PARSED=$(getopt --options=$OPTIONS --longoptions=$LONGOPTS --name "$0" -- "$@") || ( @@ -30,7 +30,7 @@ while true; do case "$1" in - -c|--real_check) + -c|--real_check|--real-check) real_check=true shift ;; diff --git a/kernel/config.aphro.example b/kernel/config.aphro.example index 04ae3db..35eb551 100644 --- a/kernel/config.aphro.example +++ b/kernel/config.aphro.example @@ -14,6 +14,7 @@ VERSION=generate CONFIG_DISABLE_MULTIBOOT2_SUPPORT=false # Panic behavior. When debugging, generally halt on panic is more useful. +# Halt on panic takes priority over spin on panic if both are enabled. CONFIG_HALT_ON_PANIC=true CONFIG_SPIN_ON_PANIC=false diff --git a/kernel/src/kernel/arch/example_impl/mod.rs b/kernel/src/kernel/arch/example_impl/mod.rs index d8a1649..f71f044 100644 --- a/kernel/src/kernel/arch/example_impl/mod.rs +++ b/kernel/src/kernel/arch/example_impl/mod.rs @@ -23,28 +23,22 @@ pub mod interrupts { pub const USER_SYSCALL_VECTOR: u16 = 0xA0; /// Returns whether interrupts are enabled or not. - #[aphrodite_proc_macros::kernel_item(InterruptsCheck)] fn interrupts_enabled() -> bool { false } /// Enables interrupts. - #[aphrodite_proc_macros::kernel_item(InterruptsEnable)] fn enable_interrupts() {} /// Disables interrupts. - #[aphrodite_proc_macros::kernel_item(InterruptsDisable)] fn disable_interrupts() {} /// Disables interrupts and a value that can be used to restore them /// with [restore_irq]. - #[aphrodite_proc_macros::kernel_item(InterruptsPop)] fn pop_irq() -> u64 { 0 } /// Restores interrupts after a [pop_irq] call. - #[aphrodite_proc_macros::kernel_item(InterruptsRestore)] fn restore_irq(_irq: u64) {} /// Activates an IDT. - #[aphrodite_proc_macros::kernel_item(ActivateIDT)] fn activate_idt(_idt: Idt) {} /// An IDT. diff --git a/kernel/src/kernel/arch/x86/gdt.rs b/kernel/src/kernel/arch/x86/gdt.rs index 0475ef8..6c74ae8 100644 --- a/kernel/src/kernel/arch/x86/gdt.rs +++ b/kernel/src/kernel/arch/x86/gdt.rs @@ -9,10 +9,14 @@ use alloc::vec::Vec; /// The GDTR. Used internally in [activate_gdt]. #[repr(C, packed)] struct Gdtr { + // raw pointer to the GDT base: *const u8, + // size of the GDT in bytes size: usize, } +/// Activates the GDT using `lgdt`. Does NOT, I repeat, does NOT change the +/// segment registers! pub unsafe fn activate_gdt(ptr: *const [u8]) { let gdtr = Gdtr { base: ptr as *const u8, diff --git a/kernel/src/kernel/arch/x86/interrupt_impls.rs b/kernel/src/kernel/arch/x86/interrupt_impls.rs new file mode 100644 index 0000000..1ea1df4 --- /dev/null +++ b/kernel/src/kernel/arch/x86/interrupt_impls.rs @@ -0,0 +1,36 @@ +//! Implementations of interrupts. +#![cfg(target_arch = "x86")] +#![allow(undefined_naked_function_abi)] // special calling convention anyway + +use core::arch::naked_asm; + +macro_rules! int_wrapper { + ($func:block, $num:expr) => { + paste::paste! { + /// autogenerated interrupt wrapper + #[naked] + pub unsafe fn [< int $num >]() { + unsafe { + naked_asm!( + "pushad", + "cld", + "call {}", + "popad", + "iret", + sym [< int $num _rust >] + ) + } + } + + /// autogenerated interrupt body + unsafe extern "C" fn [< int $num _rust >]() $func + } + }; +} + +int_wrapper!( + { + super::output::sdebugsln("Interrupt handler #0 ran"); + }, + 0 +); diff --git a/kernel/src/kernel/arch/x86/interrupts.rs b/kernel/src/kernel/arch/x86/interrupts.rs index ed08071..63d3642 100644 --- a/kernel/src/kernel/arch/x86/interrupts.rs +++ b/kernel/src/kernel/arch/x86/interrupts.rs @@ -9,7 +9,6 @@ use core::mem::MaybeUninit; pub const USER_SYSCALL_VECTOR: u16 = 0xA0; /// Returns whether interrupts are enabled or not. -#[aphrodite_proc_macros::kernel_item(InterruptsCheck)] pub fn interrupts_enabled() -> bool { let flags: u32; unsafe { @@ -22,7 +21,6 @@ pub fn interrupts_enabled() -> bool { } /// Disables interrupts. -#[aphrodite_proc_macros::kernel_item(InterruptsDisable)] pub fn disable_interrupts() { unsafe { asm!("cli") } } /// PoppedInterrupts implements drop and restores the interrupts upon being @@ -37,7 +35,6 @@ impl Drop for PoppedInterrupts { } /// Disables interrupts and returns the value of them. -#[aphrodite_proc_macros::kernel_item(InterruptsPop)] pub fn pop_irq() -> PoppedInterrupts { let flags: u32; unsafe { @@ -51,7 +48,6 @@ pub fn pop_irq() -> PoppedInterrupts { } /// Restores interrupts after a [pop_irq] call. -#[aphrodite_proc_macros::kernel_item(InterruptsRestore)] pub fn restore_irq(flags: PoppedInterrupts) { let flags = flags.0; unsafe { @@ -76,7 +72,7 @@ unsafe fn load_idt(base: *const u8, size: usize) { } #[derive(Clone, Copy)] -pub(super) struct IdtEntry { +pub struct IdtEntry { pub offset_high: u16, pub data: u16, pub segment: u16, @@ -108,8 +104,7 @@ impl From for RawIdtEntry { /// /// # Panics /// Panics if the global allocator has not been setup -#[aphrodite_proc_macros::kernel_item(ActivateIDT)] -fn activate_idt(idt: Idt) { +pub unsafe fn activate_idt(idt: Idt) { let mut entries = alloc::vec::Vec::new(); for i in 0..idt.len { if idt.using_raw[i] { @@ -195,7 +190,7 @@ fn activate_idt(idt: Idt) { #[derive(Clone, Copy)] pub struct Idt { vectors: [u16; 256], - funcs: [MaybeUninit; 256], + funcs: [MaybeUninit; 256], user_callable: [bool; 256], exception: [bool; 256], raw_entries: [IdtEntry; 256], @@ -207,7 +202,7 @@ pub struct Idt { #[derive(Clone, Copy)] pub struct IdtBuilder { vectors: [u16; 256], - funcs: [MaybeUninit; 256], + funcs: [MaybeUninit; 256], user_callable: [bool; 256], exception: [bool; 256], raw_entries: [IdtEntry; 256], @@ -238,7 +233,7 @@ impl IdtBuilder { pub fn add_fn( &mut self, vector: u16, - func: fn(), + func: unsafe fn(), user_callable: bool, exception: bool, ) -> &mut Self { diff --git a/kernel/src/kernel/arch/x86/memory.rs b/kernel/src/kernel/arch/x86/memory.rs deleted file mode 100644 index 99a946d..0000000 --- a/kernel/src/kernel/arch/x86/memory.rs +++ /dev/null @@ -1,180 +0,0 @@ -//! Hardware-level memory sections. Unimplemented for certain hardware, x86 -//! implements with GDT. -#![cfg(target_arch = "x86")] - -use core::arch::asm; - -use alloc::vec; -use alloc::vec::Vec; - -use crate::memsections::*; - -use super::gdt::{GDTEntry, write_gdt_entries}; - -/// A list of memory sections. Create one with [MemorySectionBuilder]. -pub struct MemorySections { - sections: Vec, -} - -#[repr(packed)] -struct GDTR { - address: u32, - size: u16, -} - -unsafe impl crate::memsections::MemorySections for MemorySections { - unsafe fn write(self) -> Result<(), crate::Error<'static>> { - let mut entries: Vec = vec![]; - - for section in self.sections { - let mut section: MemorySection = section; - // rust-analyzer doesn't want to cooperate and recognize that section is already - // MemorySection, so I'm telling it here. - fn make_entry(section: &mut MemorySection, entries: &mut Vec) { - if section.length == 0 { - return; - } - let mut len = section.length as u32; - while len > 0xFFFFF { - len -= 0xFFFFF; - } - let mut access = 0b10000001u8; - match section.owner { - Owner::Kernelspace => { - access |= 0b0000000; - }, - Owner::Modulespace => { - access |= 0b0100000; - }, - Owner::Userspace => { - access |= 0b1100000; - }, - } - if let SectionType::TaskSection { busy } = section.section_type { - access |= 0b00000; - if busy { - access |= 0x9; - } else { - access |= 0xB; - } - } else { - access |= 0b10000; - if let SectionType::CodeSection { - can_powerful_sections_jump, - } = section.section_type - { - access |= 0b1000; - if can_powerful_sections_jump { - access |= 0b100; - } - if section.readable { - access |= 0b10; - } - } else if section.section_type == SectionType::DataSection { - access |= 0b0000; - if section.writable { - access |= 0b10; - } - } - } - - let flags = 0b1100u8; - - let entry = GDTEntry { - limit: len, - base: section.address as u32, - access, - flags, - }; - if section.length > 0xFFFFF { - section.length -= 0xFFFFF; - } - entries.push(entry); - } - while section.length > 0xFFFFF { - make_entry(&mut section, &mut entries); - } - make_entry(&mut section, &mut entries); - } - unsafe { - let _ = super::interrupts::pop_irq(); - - let segment_entries: Vec = entries.clone(); - - let ptr = write_gdt_entries(entries)?; - - let gdtr = GDTR { - address: ptr as *const u8 as usize as u32, - size: (ptr.len() - 1) as u16, - }; - - let addr = &gdtr as *const GDTR as *const () as usize as u32; - - asm!( - "lgdt eax", - in("eax") addr - ); - - let mut code_segment = 0u16; - let mut code_set = false; - let mut data_segment = 0u16; - let mut data_set = false; - - let mut i = 0; - for entry in segment_entries { - let entry: GDTEntry = entry; - i += 1; - if code_set && data_set { - break; - } - - if entry.access & 0b11000 == 0b11000 && !code_set { - code_segment = i - 1; - code_set = true; - } else if entry.access & 0b10000 == 0b10000 && !data_set { - data_segment = i - 1; - data_set = true; - } - } - - asm!( - "jmp bx:2 ; `#[deny(named_asm_labels)]` on by default; see - 2: ; ax is already loaded with the correct value from rustland - mov ds, ax - mov es, ax - mov fs, ax - mov gs, ax - mov ss, ax", - in("bx") code_segment, - in("ax") data_segment, - options(preserves_flags, nomem, nostack) - ); - } - - Ok(()) - } -} - -/// A memory section builder. -pub struct MemorySectionBuilder { - sections: Vec, -} - -impl MemorySectionBuilder { - /// Create a new MemorySectionBuilder. - pub fn new() -> Self { MemorySectionBuilder { sections: vec![] } } - - /// Adds a section to this MemorySectionBuilder. - pub fn add_section(&mut self, section: MemorySection) -> &mut Self { - self.sections.push(section); - - self - } - - /// Finishes this MemorySectionBuilder and returns a MemorySections. - pub fn finish(self) -> MemorySections { - MemorySections { - sections: self.sections, - } - } -} diff --git a/kernel/src/kernel/arch/x86/mod.rs b/kernel/src/kernel/arch/x86/mod.rs index 8e22688..59f2bd6 100644 --- a/kernel/src/kernel/arch/x86/mod.rs +++ b/kernel/src/kernel/arch/x86/mod.rs @@ -5,8 +5,8 @@ use core::arch::asm; pub mod egatext; mod gdt; +mod interrupt_impls; pub mod interrupts; -pub mod memory; pub mod output; pub mod paging; pub mod ports; @@ -92,27 +92,63 @@ pub fn initalize_rtc() { unsafe { RTC_INITALIZED = true } } -pub fn sleep(seconds: u32) { initalize_rtc(); } - pub fn alloc_available_boot() { let irq = pop_irq(); - let mut entries = vec![]; - entries.push(gdt::GDT_NULL_ENTRY); - entries.push(GDTEntry { - limit: 0, - base: 0, - access: 0b10011011, - flags: 0b1100, - }); // kernel code segment - entries.push(GDTEntry { - limit: 0, - base: 0, - access: 0b10010011, - flags: 0b1100, - }); // + { + // GDT + let mut entries = vec![]; + entries.push(gdt::GDT_NULL_ENTRY); + entries.push(GDTEntry { + limit: 0, + base: 0, + access: 0b10011011, + flags: 0b1100, + }); // kernel code segment, segment 0x08 + entries.push(GDTEntry { + limit: 0, + base: 0, + access: 0b10010011, + flags: 0b1100, + }); // kernel data segment, segment 0x10 + entries.push(GDTEntry { + limit: 0, + base: 0, + access: 0b11111011, + flags: 0b1100, + }); // user code segment, segment 0x18 + entries.push(GDTEntry { + limit: 0, + base: 0, + access: 0b11110011, + flags: 0b1100, + }); // user data segment, segment 0x20 - unsafe { - gdt::activate_gdt(gdt::write_gdt_entries(entries).unwrap()); + unsafe { + gdt::activate_gdt(gdt::write_gdt_entries(entries).unwrap()); + } + + unsafe { + asm!( + "jmp 0x08:2", + "2:", + "mov ax, 0x10", + "mov ds, ax", + "mov es, ax", + "mov fs, ax", + "mov gs, ax", + "mov ss, ax", + out("ax") _ + ); + } + } + { + // IDT + let idt = self::interrupts::IdtBuilder::new() + .add_fn(0, interrupt_impls::int0, false, true) + .finish(); + unsafe { + interrupts::activate_idt(idt); + } } restore_irq(irq); } diff --git a/kernel/src/kernel/arch/x86/paging.rs b/kernel/src/kernel/arch/x86/paging.rs index a7cc795..c09f1f4 100644 --- a/kernel/src/kernel/arch/x86/paging.rs +++ b/kernel/src/kernel/arch/x86/paging.rs @@ -3,8 +3,6 @@ use core::arch::asm; -use aphrodite_proc_macros::kernel_item; - /// One page directory entry. Use [PageDirectoryEntry::create_fourmb] or /// [PageDirectoryEntry::create_other] to make these. pub enum PageDirectoryEntry { @@ -120,11 +118,9 @@ static mut PAGE_DIRECTORY: PageDirectoryEntry = PageDirectoryEntry::create_other(0, false, 0, false, false, false, false, false, false, false); /// Initalize paging. -#[kernel_item(PagingInit)] pub fn initalize_paging() {} /// Disables paging by clearing bit 31 in the cr0 register. -#[kernel_item(PagingDeinit)] pub fn disable_paging() { unsafe { asm!( diff --git a/kernel/src/kernel/cfg.rs b/kernel/src/kernel/cfg.rs index 38ce8eb..c00de8f 100644 --- a/kernel/src/kernel/cfg.rs +++ b/kernel/src/kernel/cfg.rs @@ -1,6 +1,6 @@ //! Config-related stuff. -/// C +/// Get configurations as a certain type #[macro_export] macro_rules! cfg_int { ($cfg:literal, $type:ident) => { diff --git a/kernel/src/kernel/indep_boot_entry.rs b/kernel/src/kernel/indep_boot_entry.rs index 4080ae5..2c441af 100644 --- a/kernel/src/kernel/indep_boot_entry.rs +++ b/kernel/src/kernel/indep_boot_entry.rs @@ -7,11 +7,8 @@ use crate::arch::output::*; use crate::display::{COLOR_DEFAULT, NoneTextDisplay}; use crate::output::*; -use aphrodite_proc_macros::*; - /// The real entrypoint to the kernel. `internel/arch/*/entry.rs` files /// eventually call this. -#[kernel_item(IndepBootEntry)] fn indep_boot_entry( display: Option<&dyn crate::display::TextDisplay>, #[allow(non_snake_case)] BI: &crate::boot::BootInfo, @@ -24,11 +21,11 @@ fn indep_boot_entry( let display = display.unwrap_or(&NoneTextDisplay {}); - display.clear_screen(COLOR_DEFAULT); + display.clear_screen(COLOR_DEFAULT).unwrap(); sreset(); let mem_map = BI.memory_map.unwrap(); - crate::mem::MemMapAllocInit(mem_map).unwrap(); + crate::mem::memory_map_alloc_init(mem_map).unwrap(); crate::arch::alloc_available_boot(); diff --git a/kernel/src/kernel/mem.rs b/kernel/src/kernel/mem.rs index f840b72..1221560 100644 --- a/kernel/src/kernel/mem.rs +++ b/kernel/src/kernel/mem.rs @@ -9,8 +9,6 @@ use core::ptr::{NonNull, null_mut}; use crate::boot::{MemoryMap, MemoryType}; -use aphrodite_proc_macros::*; - #[derive(Clone, Copy)] struct Allocation { /// Whether this allocation is used. This is used so that the @@ -65,7 +63,6 @@ static mut ALLOCATOR: MaybeMemoryMapAlloc<'static> = MaybeMemoryMapAlloc::new(No static mut ALLOCATOR_MEMMAP: MaybeUninit = MaybeUninit::uninit(); static mut ALLOCATOR_INITALIZED: bool = false; -#[kernel_item(MemMapAlloc)] pub fn get_allocator() -> Option<&'static MemoryMapAlloc<'static>> { if unsafe { ALLOCATOR_INITALIZED } { #[allow(static_mut_refs)] @@ -90,8 +87,7 @@ pub unsafe fn get_allocator_unchecked() -> &'static MemoryMapAlloc<'static> { } } -#[kernel_item(MemMapAllocInit)] -fn memory_map_alloc_init(memmap: crate::boot::MemoryMap) -> Result<(), crate::Error<'static>> { +pub fn memory_map_alloc_init(memmap: crate::boot::MemoryMap) -> Result<(), crate::Error<'static>> { #[allow(static_mut_refs)] unsafe { ALLOCATOR_MEMMAP.write(memmap); diff --git a/kernel/src/kernel/mod.rs b/kernel/src/kernel/mod.rs index 3c9c3e6..d4db6a9 100644 --- a/kernel/src/kernel/mod.rs +++ b/kernel/src/kernel/mod.rs @@ -20,6 +20,7 @@ #![allow(internal_features)] #![feature(core_intrinsics)] #![feature(vec_into_raw_parts)] +#![feature(naked_functions)] extern crate alloc; diff --git a/kernel/src/proc_macros/mod.rs b/kernel/src/proc_macros/mod.rs deleted file mode 100644 index f5b7df4..0000000 --- a/kernel/src/proc_macros/mod.rs +++ /dev/null @@ -1,62 +0,0 @@ -use proc_macro::TokenStream; -use quote::{ToTokens, quote}; -use syn::parse::{Parse, ParseStream}; -use syn::{ItemFn, Signature, Token}; - -struct KernelItemNameInput { - item: syn::Ident, -} - -impl Parse for KernelItemNameInput { - fn parse(input: ParseStream) -> syn::Result { - let item: syn::Ident = input.parse()?; - Ok(KernelItemNameInput { item }) - } -} - -fn to_tokens(signature: Signature, tokens: &mut proc_macro2::TokenStream) { - let ts = tokens; - signature.constness.to_tokens(ts); - signature.asyncness.to_tokens(ts); - signature.unsafety.to_tokens(ts); - signature.abi.to_tokens(ts); - signature.fn_token.to_tokens(ts); - signature.generics.to_tokens(ts); - signature.paren_token.surround(ts, |tokens| { - signature.inputs.to_tokens(tokens); - if let Some(variadic) = &signature.variadic { - if !signature.inputs.empty_or_trailing() { - ::default().to_tokens(tokens); - } - variadic.to_tokens(tokens); - } - }); - signature.output.to_tokens(ts); - signature.generics.where_clause.to_tokens(ts); -} - -fn to_token_stream(signature: Signature) -> proc_macro2::TokenStream { - let mut tokens = proc_macro2::TokenStream::new(); - to_tokens(signature, &mut tokens); - tokens -} - -/// Implement a kernel item. -#[proc_macro_attribute] -pub fn kernel_item(attr: TokenStream, item: TokenStream) -> TokenStream { - let name: KernelItemNameInput = syn::parse_macro_input!(attr); - let item_name = name.item; - - let input_fn = syn::parse_macro_input!(item as ItemFn); - let fn_name = input_fn.clone().sig.ident; - let fn_sig = to_token_stream(input_fn.clone().sig); - - quote! { - /// The #item_name kernel item. - #[allow(non_upper_case_globals)] - pub const #item_name: #fn_sig = #fn_name; - - #input_fn - } - .into() -}