diff --git a/.cargo/config.toml b/.cargo/config.toml index 62e08301..2f831a65 100644 --- a/.cargo/config.toml +++ b/.cargo/config.toml @@ -7,7 +7,7 @@ target = "x86_64-eduos.json" [target.i686-eduos] rustflags = [ - "-C", "link-arg=-Tsrc/arch/x86/link_i686.ld", "-C", "relocation-model=static" + "-C", "link-arg=-Tsrc/arch/x86/kernel/link_i686.ld", "-C", "relocation-model=static" ] runner = "qemu-system-x86_64 -display none -serial stdio -smp 1 -m 256M -device isa-debug-exit,iobase=0xf4,iosize=0x04 -kernel" diff --git a/src/arch/mod.rs b/src/arch/mod.rs index 36321880..9262765c 100644 --- a/src/arch/mod.rs +++ b/src/arch/mod.rs @@ -1,13 +1,17 @@ +// Implementations for x86. +#[cfg(any(target_arch = "x86_64", target_arch = "x86"))] +pub mod x86; + // Export our platform-specific modules. #[cfg(any(target_arch = "x86_64", target_arch = "x86"))] -pub use self::x86::{init, processor}; +pub use self::x86::kernel::{init, processor}; -#[cfg(all(target_arch = "x86", feature = "vga"))] -pub use self::x86::vga; +#[cfg(feature = "vga")] +pub use self::x86::kernel::vga; -#[cfg(not(all(target_arch = "x86", feature = "vga")))] -pub use self::x86::serial; +#[cfg(not(feature = "vga"))] +pub use self::x86::kernel::serial; -// Implementations for x86. +// Export our platform-specific modules. #[cfg(any(target_arch = "x86_64", target_arch = "x86"))] -pub mod x86; +pub use self::x86::mm; diff --git a/src/arch/x86/entry.s b/src/arch/x86/kernel/entry.s similarity index 51% rename from src/arch/x86/entry.s rename to src/arch/x86/kernel/entry.s index 97397767..ad0b8288 100644 --- a/src/arch/x86/entry.s +++ b/src/arch/x86/kernel/entry.s @@ -1,12 +1,8 @@ -# This is the kernel's entry point. We could either call main here, -# or we can use this to setup the stack or other nice stuff, like -# perhaps setting up the GDT and segments. Please note that interrupts -# are disabled at this point: More on interrupts later! +# Muktiboot header, which is used by the loader to detect +# a multiboot kernel .code32 -.set BOOT_STACK_SIZE, 4096 - # We use a special name to map this section at the begin of our kernel # => Multiboot expects its magic number at the beginning of the kernel. .section .mboot, "a" @@ -26,30 +22,4 @@ mboot: .4byte MULTIBOOT_HEADER_MAGIC .4byte MULTIBOOT_HEADER_FLAGS .4byte MULTIBOOT_CHECKSUM - .4byte 0, 0, 0, 0, 0 # address fields - -.section .text -.align 4 -.extern main -.extern shutdown -.global _start -_start: - cli # avoid any interrupt - - # Initialize stack pointer - mov esp, OFFSET boot_stack - add esp, BOOT_STACK_SIZE - 16 - - call main - # eax has the return value of main - push eax - call shutdown -L0: - hlt - jmp L0 - -.section .data -.align 4096 -.global boot_stack -boot_stack: - .fill BOOT_STACK_SIZE, 1, 0xcd \ No newline at end of file + .4byte 0, 0, 0, 0, 0 # address fields \ No newline at end of file diff --git a/src/arch/x86/link_i686.ld b/src/arch/x86/kernel/link_i686.ld similarity index 55% rename from src/arch/x86/link_i686.ld rename to src/arch/x86/kernel/link_i686.ld index 05504fb1..09470bea 100644 --- a/src/arch/x86/link_i686.ld +++ b/src/arch/x86/kernel/link_i686.ld @@ -4,24 +4,26 @@ phys = 0x000000100000; SECTIONS { kernel_start = phys; - .mboot phys : AT(ADDR(.mboot)) { + .mboot phys : { KEEP(*(.mboot)) KEEP(*(.mboot.*)) } - .text ALIGN(4096) : AT(ADDR(.text)) { + .text ALIGN(4) : { *(.text) *(.text.*) } - .rodata ALIGN(4096) : AT(ADDR(.rodata)) { + .rodata ALIGN(4) : { *(.rodata) *(.rodata.*) } - .data ALIGN(4096) : AT(ADDR(.data)) { + .data ALIGN(4) : { *(.data) *(.data.*) } - .bss ALIGN(4096) : AT(ADDR(.bss)) { + .bss ALIGN(4) : { + __bss_start = .; *(.bss) *(.bss.*) + __bss_end = .; } } \ No newline at end of file diff --git a/src/arch/x86/kernel/mod.rs b/src/arch/x86/kernel/mod.rs new file mode 100644 index 00000000..e2808ec9 --- /dev/null +++ b/src/arch/x86/kernel/mod.rs @@ -0,0 +1,16 @@ +pub mod processor; +#[cfg(not(feature = "vga"))] +pub mod serial; +pub mod start; +#[cfg(feature = "vga")] +pub mod vga; + +#[cfg(target_arch = "x86")] +core::arch::global_asm!(include_str!("entry.s")); + +pub fn init() { + processor::cpu_init(); + + #[cfg(all(target_arch = "x86", feature = "vga"))] + vga::init(); +} diff --git a/src/arch/x86/processor.rs b/src/arch/x86/kernel/processor.rs similarity index 100% rename from src/arch/x86/processor.rs rename to src/arch/x86/kernel/processor.rs diff --git a/src/arch/x86/serial.rs b/src/arch/x86/kernel/serial.rs similarity index 100% rename from src/arch/x86/serial.rs rename to src/arch/x86/kernel/serial.rs diff --git a/src/arch/x86/kernel/start.rs b/src/arch/x86/kernel/start.rs new file mode 100644 index 00000000..6279457f --- /dev/null +++ b/src/arch/x86/kernel/start.rs @@ -0,0 +1,68 @@ +use crate::arch; +use crate::arch::x86::kernel::processor::shutdown; + +extern "C" { + pub fn main() -> i32; +} + +#[cfg(target_arch = "x86")] +extern "C" { + static mut __bss_start: u8; + static __bss_end: u8; +} + +/// initialize bss section +#[cfg(target_arch = "x86")] +unsafe fn bss_init() { + core::ptr::write_bytes( + core::ptr::addr_of_mut!(__bss_start), + 0, + core::ptr::addr_of!(__bss_end) as usize - core::ptr::addr_of!(__bss_start) as usize, + ); +} + +#[cfg(not(test))] +unsafe extern "C" fn entry() -> ! { + arch::init(); + + #[cfg(target_arch = "x86")] + bss_init(); + + let ret = main(); + + shutdown(ret) +} + +#[cfg(not(test))] +#[cfg(target_arch = "x86_64")] +#[no_mangle] +/// # Safety +/// +/// This function is the entry point of the kernel. +/// The kernel itself should not call this function. +pub unsafe extern "C" fn _start() -> ! { + entry(); +} + +#[cfg(not(test))] +#[cfg(target_arch = "x86")] +#[no_mangle] +#[naked] +/// # Safety +/// +/// This function is the entry point of the kernel. +/// The kernel itself should not call this function. +pub unsafe extern "C" fn _start() -> ! { + use crate::arch::mm::{BOOT_STACK, BOOT_STACK_SIZE}; + use core::arch::naked_asm; + + naked_asm!( + "lea esp, {stack}", + "add esp, {offset}", + "jmp {entry}", + stack = sym BOOT_STACK, + offset = const BOOT_STACK_SIZE - 16, + entry = sym entry, + options(noreturn) + ); +} diff --git a/src/arch/x86/vga.rs b/src/arch/x86/kernel/vga.rs similarity index 100% rename from src/arch/x86/vga.rs rename to src/arch/x86/kernel/vga.rs diff --git a/src/arch/x86/mm/mod.rs b/src/arch/x86/mm/mod.rs new file mode 100644 index 00000000..dff1645c --- /dev/null +++ b/src/arch/x86/mm/mod.rs @@ -0,0 +1,18 @@ +#[cfg(target_arch = "x86")] +#[repr(C, align(64))] +pub(crate) struct Aligned(T); + +#[cfg(target_arch = "x86")] +impl Aligned { + /// Constructor. + pub const fn new(t: T) -> Self { + Self(t) + } +} + +#[cfg(target_arch = "x86")] +pub(crate) const BOOT_STACK_SIZE: usize = 0x3000; +#[cfg(target_arch = "x86")] +#[link_section = ".data"] +pub(crate) static mut BOOT_STACK: Aligned<[u8; BOOT_STACK_SIZE]> = + Aligned::new([0; BOOT_STACK_SIZE]); diff --git a/src/arch/x86/mod.rs b/src/arch/x86/mod.rs index 783f1f1e..a459fd54 100644 --- a/src/arch/x86/mod.rs +++ b/src/arch/x86/mod.rs @@ -1,17 +1,2 @@ -pub mod processor; -#[cfg(not(all(target_arch = "x86", feature = "vga")))] -pub mod serial; -#[cfg(target_arch = "x86_64")] -pub mod start; -#[cfg(all(target_arch = "x86", feature = "vga"))] -pub mod vga; - -#[cfg(target_arch = "x86")] -core::arch::global_asm!(include_str!("entry.s")); - -pub fn init() { - processor::cpu_init(); - - #[cfg(all(target_arch = "x86", feature = "vga"))] - vga::init(); -} +pub mod kernel; +pub mod mm; diff --git a/src/arch/x86/start.rs b/src/arch/x86/start.rs deleted file mode 100644 index a965b275..00000000 --- a/src/arch/x86/start.rs +++ /dev/null @@ -1,17 +0,0 @@ -use crate::arch::x86::processor::shutdown; - -extern "C" { - fn main() -> i32; -} - -#[cfg(not(test))] -#[no_mangle] -/// # Safety -/// -/// This function is the entry point of the kernel. -/// The kernel itself should not call this function. -pub unsafe extern "C" fn _start() -> ! { - let ret = main(); - // shutdown system - shutdown(ret); -}