diff --git a/GNUmakefile b/GNUmakefile index 9fc495c..19e5341 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -28,6 +28,16 @@ run-x86_64: edk2-ovmf $(IMAGE_NAME).iso -cdrom $(IMAGE_NAME).iso \ $(QEMUFLAGS) +.PHONY: debug-x86_64 +debug-x86_64: edk2-ovmf $(IMAGE_NAME).iso + qemu-system-$(KARCH) \ + -M q35 \ + -serial stdio \ + -drive if=pflash,unit=0,format=raw,file=edk2-ovmf/ovmf-code-$(KARCH).fd,readonly=on \ + -cdrom $(IMAGE_NAME).iso \ + -d in_asm,int,mmu -D /tmp/qemu_trace.log 2>/dev/null \ + $(QEMUFLAGS) + .PHONY: run-hdd-x86_64 run-hdd-x86_64: edk2-ovmf $(IMAGE_NAME).hdd qemu-system-$(KARCH) \ @@ -53,6 +63,24 @@ run-aarch64: edk2-ovmf $(IMAGE_NAME).iso -semihosting-config enable=on,target=native \ $(QEMUFLAGS) +.PHONY: debug-aarch64 +debug-aarch64: edk2-ovmf $(IMAGE_NAME).iso + qemu-system-$(KARCH) \ + -M virt,gic-version=2,secure=off \ + -cpu cortex-a72 \ + -device ramfb \ + -device qemu-xhci \ + -device usb-kbd \ + -device usb-mouse \ + -device virtio-keyboard-device \ + -device virtio-mouse-device \ + -serial stdio \ + -drive if=pflash,unit=0,format=raw,file=edk2-ovmf/ovmf-code-$(KARCH).fd,readonly=on \ + -cdrom $(IMAGE_NAME).iso \ + -semihosting-config enable=on,target=native \ + -d in_asm,int,mmu -D /tmp/qemu_trace.log 2>/dev/null + $(QEMUFLAGS) + .PHONY: run-hdd-aarch64 run-hdd-aarch64: edk2-ovmf $(IMAGE_NAME).hdd qemu-system-$(KARCH) \ diff --git a/assets/.gitignore b/assets/.gitignore index 8455f43..ed163ad 100644 --- a/assets/.gitignore +++ b/assets/.gitignore @@ -1,2 +1,3 @@ doomgeneric* init +helloworld* diff --git a/assets/helloworld.elf b/assets/helloworld.elf deleted file mode 100755 index bb6ee7d..0000000 Binary files a/assets/helloworld.elf and /dev/null differ diff --git a/build_doomgeneric.sh b/build_doomgeneric.sh index d825ab7..e79bd6a 100644 --- a/build_doomgeneric.sh +++ b/build_doomgeneric.sh @@ -1,6 +1,6 @@ bash build_libxunil.sh cd user/apps/doomgeneric/doomgeneric rm -r ./build -make LD=/usr/bin/ld -j16 -f Makefile.xunil -cp doomgeneric ../../../../assets/doomgeneric +make -j16 -f Makefile.xunil +cp doomgeneric ../../../../assets/$KARCH/doomgeneric cd ../../../.. diff --git a/build_init.sh b/build_init.sh index 857fa54..bc0d829 100644 --- a/build_init.sh +++ b/build_init.sh @@ -1,5 +1,5 @@ bash build_libxunil.sh cd user/init -cargo build --target x86_64-unknown-none --release -cp ./target/x86_64-unknown-none/release/init ../../assets/init +cargo build --target $KARCH-unknown-none --release --config profile.release.debug=true +cp ./target/$KARCH-unknown-none/release/init ../../assets/$KARCH/init cd ../.. diff --git a/build_libxunil.sh b/build_libxunil.sh index c34f2a8..b529599 100644 --- a/build_libxunil.sh +++ b/build_libxunil.sh @@ -1,2 +1,2 @@ cd user/libxunil -cargo build --release +cargo build --target $KARCH-unknown-none --release --config profile.release.debug=true diff --git a/config.mk b/config.mk index 68efdd7..152d679 100644 --- a/config.mk +++ b/config.mk @@ -1,4 +1,4 @@ export KARCH ?= aarch64 export OUTPUT ?= kernel -export MEMORY ?= 512M +export MEMORY ?= 1G export TIMER_FREQUENCY_HZ ?= 1000 diff --git a/kernel/GNUmakefile b/kernel/GNUmakefile index e99dba0..ec8d4d2 100644 --- a/kernel/GNUmakefile +++ b/kernel/GNUmakefile @@ -12,7 +12,7 @@ ifeq ($(RUST_TARGET),) endif ifeq ($(RUST_PROFILE),) - override RUST_PROFILE := dev + override RUST_PROFILE := release endif override RUST_PROFILE_SUBDIR := $(RUST_PROFILE) @@ -23,7 +23,8 @@ endif # Default target. .PHONY: all all: - RUSTFLAGS="-C relocation-model=static" cargo build --target $(RUST_TARGET) --profile $(RUST_PROFILE) + RUSTFLAGS="-C relocation-model=static" cargo build --target $(RUST_TARGET) --profile $(RUST_PROFILE) --config profile.release.debug=true + cp target/$(RUST_TARGET)/$(RUST_PROFILE_SUBDIR)/$$(cd target/$(RUST_TARGET)/$(RUST_PROFILE_SUBDIR) && find -maxdepth 1 -perm -111 -type f) kernel # Remove object files and the final executable. diff --git a/kernel/build.rs b/kernel/build.rs index 87dca85..cf93bfa 100644 --- a/kernel/build.rs +++ b/kernel/build.rs @@ -15,6 +15,14 @@ fn main() { ) .unwrap(); + let out_dir = out_dir.join("driver").join("io").join("fs"); + + fs::write( + out_dir.join("assets.rs"), + format!("pub static INIT_ELF: &[u8] = include_bytes!(\"../../../../../assets/{karch}/init\");\npub static DOOM_WAD: &[u8] = include_bytes!(\"../../../../../assets/doom1.wad\");\npub static DOOM_ELF: &[u8] = include_bytes!(\"../../../../../assets/{karch}/doomgeneric\");\npub static HELLOWORLD_ELF: &[u8] = include_bytes!(\"../../../../../assets/{karch}/helloworld.elf\");"), + ) + .unwrap(); + println!("cargo:rerun-if-env-changed=KARCH"); println!("cargo:rerun-if-env-changed=TIMER_FREQUENCY_HZ"); println!("cargo:rerun-if-env-changed=OUTPUT"); diff --git a/kernel/src/arch/aarch64/init.rs b/kernel/src/arch/aarch64/init.rs index a6fc9ef..5b0855b 100644 --- a/kernel/src/arch/aarch64/init.rs +++ b/kernel/src/arch/aarch64/init.rs @@ -4,8 +4,7 @@ use crate::{ interrupts::init_interrupts, paging::{AArchPageTable, initialize_paging_aarch64}, }, - config::TIMER_FREQUENCY_HZ, - driver::io::virtio::scan_devices, + driver::io::virtio::scan_virtio_devices, }; use limine::response::{ExecutableAddressResponse, HhdmResponse, MemoryMapResponse}; @@ -15,12 +14,6 @@ pub struct Stack(pub [u8; 64 * 1024]); pub static KERNEL_STACK: Stack = Stack([0; 64 * 1024]); -pub fn set_timer_freq(freq: usize) { - unsafe { - core::arch::asm!("mrs {}, cntp_tval_el0", "isb", in(reg) freq); - } -} - #[unsafe(naked)] pub unsafe fn init_aarch64_trampoline(mapper: &mut AArchPageTable) { // fix stack, since limine's bootloader stack is not mapped @@ -38,8 +31,7 @@ pub unsafe fn init_aarch64_trampoline(mapper: &mut AArchPageTable) { #[unsafe(no_mangle)] pub extern "C" fn init_aarch64(mapper: &mut AArchPageTable) { init_heap(mapper); - set_timer_freq(TIMER_FREQUENCY_HZ); - scan_devices(); + scan_virtio_devices(); init_interrupts(); } diff --git a/kernel/src/arch/aarch64/interrupts.rs b/kernel/src/arch/aarch64/interrupts.rs index 88c6473..8be82d1 100644 --- a/kernel/src/arch/aarch64/interrupts.rs +++ b/kernel/src/arch/aarch64/interrupts.rs @@ -1,7 +1,7 @@ use core::{arch::global_asm, sync::atomic::Ordering}; use crate::{ - arch::syscall::syscall_dispatch, + arch::syscall::{check_and_reschedule, syscall_dispatch}, config::TIMER_FREQUENCY_HZ, driver::{ graphics::framebuffer::with_framebuffer, @@ -9,11 +9,9 @@ use crate::{ serial::with_serial_console, timer::TIMER, }, - task::context::UserContext, + task::context::{UserContext, ctx_save}, }; -use aarch64_cpu::registers::{DAIF, Writeable}; - global_asm!( r#" .section .text.vectors @@ -43,6 +41,12 @@ global_asm!( "# ); +fn timer_ticks_per_irq() -> u64 { + let cntfrq: u64; + unsafe { core::arch::asm!("mrs {}, cntfrq_el0", out(reg) cntfrq) }; + cntfrq / (TIMER_FREQUENCY_HZ as u64) +} + // stp allows storing in pairs, ldp loads in pairs macro_rules! exception_handler { ($name:ident, $rust_handler:ident) => { @@ -66,6 +70,8 @@ macro_rules! exception_handler { "stp x24, x25, [sp, #192]", "stp x26, x27, [sp, #208]", "stp x28, x29, [sp, #224]", + "mrs x2, sp_el0", + "str x2, [sp, #280]", "mrs x0, elr_el1", "mrs x1, spsr_el1", "stp x30, x0, [sp, #240]", @@ -75,6 +81,8 @@ macro_rules! exception_handler { "stp x2, x3, [sp, #264]", "mov x0, sp", concat!("bl ", stringify!($rust_handler)), + "ldr x2, [sp, #280]", + "msr sp_el0, x2", "ldr x1, [sp, #256]", "ldp x30, x0, [sp, #240]", "msr spsr_el1, x1", @@ -155,6 +163,7 @@ unsafe fn gic_eoi(id: u32) { pub fn init_interrupts() { unsafe { use_exception_vectors() }; unsafe { gic_init() }; + enable_interrupts(); unsafe { core::arch::asm!("isb") }; } @@ -168,14 +177,14 @@ pub fn enable_interrupts() { gic_enable_interrupt(keyboard_irq as u32); gic_enable_interrupt(mouse_irq as u32); + let ticks = timer_ticks_per_irq(); + core::arch::asm!("msr cntp_tval_el0, {}", in(reg) ticks); core::arch::asm!("msr cntp_ctl_el0, {}", in(reg) 1u64); // enable timer } - DAIF.write(DAIF::D::Masked + DAIF::A::Masked + DAIF::I::Unmasked + DAIF::F::Masked); } #[allow(unused_variables, dead_code)] #[unsafe(no_mangle)] - unsafe extern "C" fn no_operation(ctx: *mut UserContext) { let interrupt_id = unsafe { gic_acknowledge() }; @@ -200,15 +209,14 @@ unsafe extern "C" fn irq_handler(ctx: *mut UserContext) { if t % 60 == 0 { with_framebuffer(|fb| { - with_serial_console(|serial_console| { - serial_console.print(".", fb); - serial_console.render(fb) - }); + with_serial_console(|serial_console| serial_console.render(fb)); fb.present(); }); } - unsafe { core::arch::asm!("msr cntp_tval_el0, {}", in(reg) TIMER_FREQUENCY_HZ) }; + let ticks = timer_ticks_per_irq(); + unsafe { core::arch::asm!("msr cntp_tval_el0, {}", in(reg) ticks) }; + unsafe { core::arch::asm!("msr cntp_ctl_el0, {}", in(reg) 1u64) }; } interrupt_id if keyboard_irq == interrupt_id as u64 => { input_interrupt("kbd"); @@ -227,13 +235,13 @@ unsafe extern "C" fn irq_handler(ctx: *mut UserContext) { fn handle_aborts(ec: u64, ctx: &UserContext) { match ec { - 0x25 => { + ec if ec == 0x25 || ec == 0x24 => { panic!( "Data abort at VA={:#x} ELR={:#x} ESR={:#x}", ctx.far_el1, ctx.elr_el1, ctx.esr_el1 ); } - 0x21 => { + ec if ec == 0x21 || ec == 0x20 => { panic!( "Instruction abort at VA={:#x} ELR={:#x}", ctx.far_el1, ctx.elr_el1 @@ -241,8 +249,8 @@ fn handle_aborts(ec: u64, ctx: &UserContext) { } _ => { panic!( - "Unhandled sync abort VA={:#x} ELR={:#x} ESR={:#x}", - ctx.far_el1, ctx.elr_el1, ctx.esr_el1 + "Unhandled sync abort VA={:#x} ELR={:#x} ESR={:#x}, ec={:#x}", + ctx.far_el1, ctx.elr_el1, ctx.esr_el1, ec ); } } @@ -250,10 +258,9 @@ fn handle_aborts(ec: u64, ctx: &UserContext) { #[unsafe(no_mangle)] unsafe extern "C" fn sync_handler_user(ctx: *mut UserContext) { - let mut ctx = unsafe { *ctx }; + let ctx = unsafe { &mut *ctx }; let ec = (ctx.esr_el1 >> ESR_EC_SHIFT) & ESR_EC_MASK; - #[allow(unused_assignments)] match ec { EC_SVC_AA64 => { ctx.x0 = unsafe { @@ -267,9 +274,13 @@ unsafe extern "C" fn sync_handler_user(ctx: *mut UserContext) { ctx.x5 as isize, ) } as u64; + + ctx_save(ctx as *const UserContext); + + let _ = unsafe { check_and_reschedule() }; } - _ => handle_aborts(ec, &ctx), - } + _ => handle_aborts(ec, ctx), + }; } #[unsafe(no_mangle)] @@ -279,6 +290,37 @@ unsafe extern "C" fn sync_handler_kernel(ctx: *mut UserContext) { handle_aborts(ec, &ctx) } +#[unsafe(naked)] +#[unsafe(no_mangle)] +pub unsafe fn run_next(ctx: *const UserContext, user_sp: u64) { + core::arch::naked_asm!( + "mov x30, x0", + "msr sp_el0, x1", + "ldr x2, [x30, #248]", + "msr elr_el1, x2", + "ldr x3, [x30, #256]", + "msr spsr_el1, x3", + "ldp x0, x1, [x30, #0]", + "ldp x2, x3, [x30, #16]", + "ldp x4, x5, [x30, #32]", + "ldp x6, x7, [x30, #48]", + "ldp x8, x9, [x30, #64]", + "ldp x10, x11, [x30, #80]", + "ldp x12, x13, [x30, #96]", + "ldp x14, x15, [x30, #112]", + "ldp x16, x17, [x30, #128]", + "ldp x18, x19, [x30, #144]", + "ldp x20, x21, [x30, #160]", + "ldp x22, x23, [x30, #176]", + "ldp x24, x25, [x30, #192]", + "ldp x26, x27, [x30, #208]", + "ldp x28, x29, [x30, #224]", + "ldr x30, [x30, #240]", + "isb", + "eret" + ); +} + // these are UB and should not happen exception_handler!(current_el_sp0_sync, no_operation); exception_handler!(current_el_sp0_irq, no_operation); diff --git a/kernel/src/arch/aarch64/kmi.rs b/kernel/src/arch/aarch64/kmi.rs deleted file mode 100644 index bd2ffd5..0000000 --- a/kernel/src/arch/aarch64/kmi.rs +++ /dev/null @@ -1,87 +0,0 @@ -use crate::arch::arch::safe_lock; - -const KMI0_BASE: u64 = 0xFFFF_0000_0905_0000; -const KMI1_BASE: u64 = 0xFFFF_0000_0906_0000; -const KMI_CR: u64 = 0x00; -const KMI_STAT: u64 = 0x04; -const KMI_DATA: u64 = 0x08; - -pub unsafe fn kmi_write(base: u64, kmi_type: u64, val: u8) { - let data = (base + kmi_type) as *mut u32; - unsafe { data.write_volatile(val as u32) }; -} - -pub fn kmi_read(base: u64, kmi_type: u64) -> u8 { - let data = (base + kmi_type) as *const u32; - unsafe { data.read_volatile() as u8 } -} - -pub unsafe fn read_mouse_control() -> u8 { - kmi_read(KMI1_BASE, KMI_STAT) -} - -pub unsafe fn read_mouse_data() -> u8 { - kmi_read(KMI1_BASE, KMI_DATA) -} - -pub unsafe fn read_keyboard_control() -> u8 { - kmi_read(KMI0_BASE, KMI_STAT) -} -pub unsafe fn read_keyboard_data() -> u8 { - kmi_read(KMI0_BASE, KMI_DATA) -} - -pub unsafe fn setup_kmi() -> u8 { - safe_lock(|| unsafe { - let cr0 = (KMI0_BASE + KMI_CR) as *mut u32; - cr0.write_volatile(0x14); // enable keyboard - - kmi_write(KMI0_BASE, KMI_DATA, 0xFF); // reset keyboard - - if kmi_read(KMI0_BASE, KMI_DATA) != 0xFA { - // ACK - return 2; - } - - if kmi_read(KMI0_BASE, KMI_DATA) != 0xAA { - // self-test passed - return 3; - } - - kmi_write(KMI0_BASE, KMI_DATA, 0xF4); // enable keyboard data reporting - - if kmi_read(KMI0_BASE, KMI_DATA) != 0xFA { - // ACK - return 4; - } - - let cr1 = (KMI1_BASE + KMI_CR) as *mut u32; - cr1.write_volatile(0x14); // enable mouse - - kmi_write(KMI1_BASE, KMI_DATA, 0xFF); // reset mouse - - if kmi_read(KMI1_BASE, KMI_DATA) != 0xFA { - // ACK - return 5; - } - - if kmi_read(KMI1_BASE, KMI_DATA) != 0xAA { - // self-test passed - return 6; - } - - if kmi_read(KMI1_BASE, KMI_DATA) != 0x00 { - // mouse ID - return 7; - } - - kmi_write(KMI1_BASE, KMI_DATA, 0xF4); // enable mouse data reporting - - if kmi_read(KMI1_BASE, KMI_DATA) != 0xFA { - // ACK - return 8; - } - - return 9; - }) -} diff --git a/kernel/src/arch/aarch64/mod.rs b/kernel/src/arch/aarch64/mod.rs index 10691a4..86fb8e3 100644 --- a/kernel/src/arch/aarch64/mod.rs +++ b/kernel/src/arch/aarch64/mod.rs @@ -2,7 +2,5 @@ pub mod dtb; pub mod heap; pub mod init; pub mod interrupts; -pub mod kmi; pub mod paging; -pub mod syscall; pub mod usermode; diff --git a/kernel/src/arch/aarch64/paging.rs b/kernel/src/arch/aarch64/paging.rs index c4f9c87..66ec6fa 100644 --- a/kernel/src/arch/aarch64/paging.rs +++ b/kernel/src/arch/aarch64/paging.rs @@ -1,10 +1,11 @@ -use core::sync::atomic::{AtomicBool, Ordering}; +use core::sync::atomic::Ordering; use crate::{ arch::{ aarch64::init::KERNEL_STACK, arch::{HHDM_OFFSET, XunilFrameAllocator, safe_lock, serial_print}, }, + driver::graphics::framebuffer::USER_FB_BASE, util::U64Buf, }; use limine::{ @@ -56,21 +57,12 @@ pub fn device_flags() -> u64 { // no SH bits for device memory } -static HHDM_OVERFLOW_REPORTED: AtomicBool = AtomicBool::new(false); - fn phys_to_virt(phys: u64) -> *mut u64 { let hhdm_offset = HHDM_OFFSET.load(Ordering::Relaxed); match phys.checked_add(hhdm_offset) { Some(virt) => virt as *mut u64, None => { - if !HHDM_OVERFLOW_REPORTED.swap(true, Ordering::Relaxed) { - serial_print("HHDM overflow phys="); - serial_print(U64Buf::new(phys).as_str()); - serial_print(", hhdm_offset="); - serial_print(U64Buf::new(hhdm_offset).as_str()); - serial_print("\n"); - } panic!("phys_to_virt overflow"); } } @@ -184,7 +176,8 @@ pub fn initialize_paging_aarch64<'a>( page_table.map_range(0xFFFF_0000_0900_0000, 0x0900_0000, 0x1000, device_flags()); // the UART page_table.map_range(0xFFFF_0000_0800_0000, 0x0800_0000, 0x10000, device_flags()); // the GICD page_table.map_range(0xFFFF_0000_0801_0000, 0x0801_0000, 0x10000, device_flags()); // the GICC - page_table.map_range(0xFFFF_0000_0a00_0000, 0x0a00_0000, 0x8000, device_flags()); // Virtio setup_mair(); + page_table.map_range(0xFFFF_0000_0a00_0000, 0x0a00_0000, 0x8000, device_flags()); // Virtio + setup_mair(); setup_tcr(); let stack_phys = KERNEL_STACK.0.as_ptr() as u64 - k_virt_base + k_phys_base; @@ -259,6 +252,30 @@ impl AArchPageTable { unsafe { entry_ptr.write_volatile(phys | flags); } + + if virt == USER_FB_BASE + 0x1000 { + serial_print("entry_ptr="); + serial_print(U64Buf::new(entry_ptr as u64).as_str()); + serial_print(", virt="); + serial_print(U64Buf::new(virt as u64).as_str()); + serial_print(", phys="); + serial_print(U64Buf::new(phys as u64).as_str()); + serial_print(", l0="); + serial_print(U64Buf::new(l0 as u64).as_str()); + serial_print(", l1="); + serial_print(U64Buf::new(l1 as u64).as_str()); + serial_print(", l2="); + serial_print(U64Buf::new(l2 as u64).as_str()); + serial_print(", l3="); + serial_print(U64Buf::new(l3 as u64).as_str()); + serial_print(", flags="); + serial_print(U64Buf::new(flags).as_str()); + + let written = unsafe { entry_ptr.read_volatile() }; + serial_print(", readback="); + serial_print(U64Buf::new(written).as_str()); + serial_print("\n"); + } } pub fn map_range(&self, virt: u64, phys: u64, size: u64, flags: u64) { @@ -302,17 +319,12 @@ pub fn create_and_map_multiple_pages( base: u64, flags: u64, ) { - let mut frame_allocator = FRAME_ALLOCATOR_AARCH64.lock(); - for i in 0..page_count { - let frame = frame_allocator.allocate_frame().unwrap(); + let frame = alloc_frame().unwrap(); let virt = base + i as u64 * 4096; - mapper.map_page(virt, frame, flags); } tlb_flush(); - - drop(frame_allocator); } diff --git a/kernel/src/arch/aarch64/syscall.rs b/kernel/src/arch/aarch64/syscall.rs deleted file mode 100644 index 1325e4c..0000000 --- a/kernel/src/arch/aarch64/syscall.rs +++ /dev/null @@ -1 +0,0 @@ -// TODO: add syscalls diff --git a/kernel/src/arch/arch.rs b/kernel/src/arch/arch.rs index 6e27d83..65b261c 100644 --- a/kernel/src/arch/arch.rs +++ b/kernel/src/arch/arch.rs @@ -11,6 +11,9 @@ use x86_64::{ structures::paging::{FrameAllocator, OffsetPageTable, PhysFrame, Size4KiB}, }; +#[cfg(target_arch = "aarch64")] +use aarch64_cpu::registers::{DAIF, Writeable}; + #[cfg(target_arch = "aarch64")] pub use crate::arch::aarch64::paging::FRAME_ALLOCATOR_AARCH64 as FRAME_ALLOCATOR; #[cfg(target_arch = "aarch64")] @@ -91,8 +94,11 @@ impl XunilFrameAllocator { } #[cfg(target_arch = "x86_64")] -pub fn init<'a>(hhdm_response: &HhdmResponse, memory_map_response: &'a MemoryMapResponse) { - init_x86_64(hhdm_response, memory_map_response); +pub fn init<'a>( + hhdm_response: &HhdmResponse, + memory_map_response: &'a MemoryMapResponse, +) -> OffsetPageTable<'a> { + init_x86_64(hhdm_response, memory_map_response) } #[cfg(target_arch = "aarch64")] @@ -110,11 +116,26 @@ pub fn enter_usermode(entry: u64, stack_ptr: u64, should_swapgs: bool) { enter_usermode_aarch64(entry, stack_ptr, should_swapgs); } +#[cfg(target_arch = "x86_64")] pub fn safe_lock R>(f: F) -> R { - #[cfg(target_arch = "x86_64")] return without_interrupts(|| f()); - #[cfg(target_arch = "aarch64")] - return f(); +} + +#[cfg(target_arch = "aarch64")] +pub fn safe_lock R>(f: F) -> R { + // #[cfg(target_arch = "aarch64")] + // { + // DAIF.write(DAIF::D::Masked + DAIF::A::Masked + DAIF::I::Masked + DAIF::F::Masked); + // } + + let r = f(); + + // #[cfg(target_arch = "aarch64")] + // { + // DAIF.write(DAIF::D::Masked + DAIF::A::Masked + DAIF::I::Unmasked + DAIF::F::Masked); + // } + + r } #[cfg(target_arch = "x86_64")] @@ -157,6 +178,10 @@ pub fn idle() { pub fn sleep(ticks: u64) { let start = TIMER.now(); while start.ticks_since() < ticks { + #[cfg(target_arch = "aarch64")] + { + DAIF.write(DAIF::D::Masked + DAIF::A::Masked + DAIF::I::Unmasked + DAIF::F::Masked); + } idle(); } } diff --git a/kernel/src/arch/syscall.rs b/kernel/src/arch/syscall.rs index 7ac6e91..2fee96d 100644 --- a/kernel/src/arch/syscall.rs +++ b/kernel/src/arch/syscall.rs @@ -18,7 +18,7 @@ use crate::driver::io::ps2::process_scancodes; #[cfg(target_arch = "aarch64")] use crate::driver::io::virtio::input::process_keycodes; use crate::{ - arch::arch::{FRAME_ALLOCATOR, sleep}, + arch::arch::{FRAME_ALLOCATOR, serial_print, sleep}, driver::{ elf::loader::run_elf, graphics::framebuffer::{FRAMEBUFFER, USER_FB_BASE, with_framebuffer}, @@ -33,7 +33,7 @@ use crate::{ process::ProcessState, scheduler::{SCHEDULER, current_pid}, }, - util::{align_down, align_up}, + util::{U64Buf, align_down, align_up}, }; use crate::{ @@ -363,7 +363,7 @@ pub fn exec(arg0: isize) -> isize { return -1; } - run_elf(&buf, true); + run_elf(&buf, true, false); 0 } @@ -384,6 +384,7 @@ pub fn set_reschedule(should_reschedule: bool) { } pub fn exit() -> isize { + serial_print("Process Exited."); let pid = current_pid().unwrap_or(0); if pid == 0 { return 0; @@ -414,6 +415,33 @@ pub fn exit() -> isize { crate::arch::arch::infinite_idle(); } +#[unsafe(no_mangle)] +pub unsafe extern "C" fn check_and_reschedule() -> usize { + let pid = current_pid().unwrap_or(0); + + if pid == 0 { + return 0; + } + + let should = SCHEDULER + .with_process(pid, |process| process.should_reschedule) + .unwrap_or(false); + + if !should { + return 0; + } + + let next_task = SCHEDULER.next_task(); + + if next_task == pid { + return 0; + } + + SCHEDULER.switch_to(next_task, true); + + 1 +} + #[allow(unused_variables)] #[unsafe(no_mangle)] pub unsafe extern "C" fn syscall_dispatch( @@ -427,20 +455,25 @@ pub unsafe extern "C" fn syscall_dispatch( ) -> isize { #[cfg(target_arch = "x86_64")] interrupts::enable(); + // if num != 1 { + // serial_print("syscall num="); + // serial_print(U64Buf::new(num as u64).as_str()); + // serial_print("\n"); + // } set_reschedule(match num { BRK => false, - READ => true, + READ => false, WRITE => false, OPEN => true, CLOSE => true, - LSEEK => true, + LSEEK => false, EXIT => true, SLEEP => true, CLOCK_GETTIME => false, MAP_FRAMEBUFFER => false, - KBD_READ => true, - FRAMEBUFFER_SWAP => true, + KBD_READ => false, + FRAMEBUFFER_SWAP => false, GETPID => false, EXECVE => true, _ => false, diff --git a/kernel/src/arch/x86_64/heap.rs b/kernel/src/arch/x86_64/heap.rs index 733daca..9a498ac 100644 --- a/kernel/src/arch/x86_64/heap.rs +++ b/kernel/src/arch/x86_64/heap.rs @@ -9,7 +9,7 @@ use x86_64::structures::paging::{ pub static ALLOCATOR: Locked = Locked::new(LinkedListAllocator::new()); pub const HEAP_START: usize = 0xffffffff90000000; -pub const HEAP_SIZE: usize = 64 * 1024 * 1024; // 64 MiB +pub const HEAP_SIZE: usize = 4 * 1024 * 1024; // 64 MiB pub fn init_heap(mapper: &mut OffsetPageTable) -> Result<(), MapToError> { let page_count = HEAP_SIZE / 4096; diff --git a/kernel/src/arch/x86_64/init.rs b/kernel/src/arch/x86_64/init.rs index d0f5584..5fd3993 100644 --- a/kernel/src/arch/x86_64/init.rs +++ b/kernel/src/arch/x86_64/init.rs @@ -47,7 +47,10 @@ pub fn set_pit_interval() { }); } -pub fn init_x86_64<'a>(hhdm_response: &HhdmResponse, memory_map_response: &'a MemoryMapResponse) { +pub fn init_x86_64<'a>( + hhdm_response: &HhdmResponse, + memory_map_response: &'a MemoryMapResponse, +) -> OffsetPageTable<'a> { load_gdt_x86_64(); unsafe { @@ -87,4 +90,6 @@ pub fn init_x86_64<'a>(hhdm_response: &HhdmResponse, memory_map_response: &'a Me .expect("Failed to initalize heap"); MOUSE.set_status(kmi_status); + + return mapper; } diff --git a/kernel/src/arch/x86_64/interrupts.rs b/kernel/src/arch/x86_64/interrupts.rs index fcc44ae..d4cbfe3 100644 --- a/kernel/src/arch/x86_64/interrupts.rs +++ b/kernel/src/arch/x86_64/interrupts.rs @@ -1,7 +1,7 @@ use core::sync::atomic::Ordering; use crate::{ - arch::x86_64::gdt, + arch::{arch::serial_print, x86_64::gdt}, driver::{ graphics::framebuffer::with_framebuffer, io::ps2::{keyboard_interrupt, mouse_interrupt, push_scancode}, @@ -9,6 +9,7 @@ use crate::{ timer::TIMER, }, println, + util::U64Buf, }; use lazy_static::lazy_static; use pic8259::ChainedPics; diff --git a/kernel/src/arch/x86_64/syscall.rs b/kernel/src/arch/x86_64/syscall.rs index ec89269..9b6a222 100644 --- a/kernel/src/arch/x86_64/syscall.rs +++ b/kernel/src/arch/x86_64/syscall.rs @@ -4,7 +4,7 @@ use x86_64::instructions::tlb::flush_all; use crate::{ arch::x86_64::gdt::{GDT, TSS}, - task::scheduler::{SCHEDULER, current_pid}, + task::context::UserContext, }; const IA32_EFER: u32 = 0xC0000080; @@ -85,33 +85,6 @@ pub fn init_syscalls() { } } -#[unsafe(no_mangle)] -unsafe extern "C" fn check_and_reschedule() -> usize { - let pid = current_pid().unwrap_or(0); - - if pid == 0 { - return 0; - } - - let should = SCHEDULER - .with_process(pid, |process| process.should_reschedule) - .unwrap_or(false); - - if !should { - return 0; - } - - let next_task = SCHEDULER.next_task(); - - if next_task == pid { - return 0; - } - - SCHEDULER.switch_to(next_task, false); - - 1 -} - #[unsafe(naked)] #[unsafe(no_mangle)] unsafe extern "C" fn syscall_entry() { @@ -206,3 +179,30 @@ unsafe extern "C" fn syscall_entry() { "#, ); } + +#[unsafe(naked)] +#[unsafe(no_mangle)] +pub unsafe fn run_next(ctx: *const UserContext, user_rsp: u64) { + core::arch::naked_asm!( + "mov gs:[0], rsi", // store new user rsp + "mov rsp, rdi", + "mov r15, qword ptr [rsp + 0]", + "mov r14, qword ptr [rsp + 8]", + "mov r13, qword ptr [rsp + 16]", + "mov r12, qword ptr [rsp + 24]", + "mov r11, qword ptr [rsp + 32]", // rflags + "mov r10, qword ptr [rsp + 40]", + "mov r9, qword ptr [rsp + 48]", + "mov r8, qword ptr [rsp + 56]", + "mov rsi, qword ptr [rsp + 64]", + "mov rdi, qword ptr [rsp + 72]", + "mov rbp, qword ptr [rsp + 80]", + "mov rdx, qword ptr [rsp + 88]", + "mov rcx, qword ptr [rsp + 96]", // rip + "mov rbx, qword ptr [rsp + 104]", + "mov rax, qword ptr [rsp + 112]", + "mov rsp, qword ptr [rsp + 120]", // user rsp + "swapgs", + "sysretq", + ); +} diff --git a/kernel/src/config.rs b/kernel/src/config.rs index 82f0fdc..1a3ed00 100644 --- a/kernel/src/config.rs +++ b/kernel/src/config.rs @@ -1,2 +1,2 @@ pub const TIMER_FREQUENCY_HZ: usize = 1000; -pub const KARCH: &str = "aarch64"; \ No newline at end of file +pub const KARCH: &str = "x86_64"; \ No newline at end of file diff --git a/kernel/src/driver/elf/header.rs b/kernel/src/driver/elf/header.rs index 0733d4d..7adc083 100644 --- a/kernel/src/driver/elf/header.rs +++ b/kernel/src/driver/elf/header.rs @@ -144,6 +144,7 @@ pub const DT_VERNEED: i64 = 0x6ffffffe; pub const DT_VERNEEDNUM: i64 = 0x6fffffff; #[repr(C)] +#[derive(Debug)] pub struct Elf64Ehdr { pub e_ident: [u8; 16], pub e_type: u16, diff --git a/kernel/src/driver/elf/loader.rs b/kernel/src/driver/elf/loader.rs index 4f30a41..0fee253 100644 --- a/kernel/src/driver/elf/loader.rs +++ b/kernel/src/driver/elf/loader.rs @@ -59,7 +59,7 @@ pub fn load_file(mapper: &mut PageTable, elf_bytes: &[u8]) -> (*const u8, u64) { unsafe { core::ptr::read_unaligned(elf_bytes.as_ptr() as *const Elf64Ehdr) }; if !validate_elf(&elf_header, elf_bytes.len()) { - return (null(), 0); + panic!("Invalid ELF"); } let elf_header_ptr = elf_bytes.as_ptr() as *const Elf64Ehdr; @@ -72,7 +72,7 @@ pub fn load_file(mapper: &mut PageTable, elf_bytes: &[u8]) -> (*const u8, u64) { }; } -pub fn run_elf(file_bytes: &[u8], should_swapgs: bool) { +pub fn run_elf(file_bytes: &[u8], should_swapgs: bool, switch_to: bool) { let stack_base: u64 = 0x0000_7fff_0000_0000; let page_count = 4096; // 16 mib let page_size = 0x1000u64; @@ -109,7 +109,9 @@ pub fn run_elf(file_bytes: &[u8], should_swapgs: bool) { process.address_space = Some(address_space) }); - SCHEDULER.switch_to(process_pid, should_swapgs); + if switch_to { + SCHEDULER.switch_to(process_pid, should_swapgs); + } } else { return; }; diff --git a/kernel/src/driver/elf/program.rs b/kernel/src/driver/elf/program.rs index d48f36f..6b678a3 100644 --- a/kernel/src/driver/elf/program.rs +++ b/kernel/src/driver/elf/program.rs @@ -21,7 +21,6 @@ use x86_64::{ use crate::arch::x86_64::paging::create_and_map_multiple_pages; #[allow(unused_imports)] use crate::{ - arch::arch::FRAME_ALLOCATOR, driver::elf::header::{ DT_JMPREL, DT_NEEDED, DT_NULL, DT_PLTREL, DT_PLTRELSZ, DT_RELA, DT_RELASZ, DT_STRSZ, DT_STRTAB, DT_SYMTAB, Elf64Dyn, Elf64Ehdr, Elf64Phdr, Elf64Rela, Elf64Sym, PF_X, @@ -319,9 +318,13 @@ pub fn load_segment_to_memory( } #[cfg(target_arch = "aarch64")] { - let mut flags = user_code_flags(); + use crate::arch::aarch64::paging::user_data_flags; - if unsafe { ((*phdr).p_flags & PF_X) == 0 } { + let mut flags = user_data_flags(); + + if unsafe { ((*phdr).p_flags & PF_X) != 0 } { + flags &= !UXN; + } else { flags |= UXN; } @@ -336,7 +339,6 @@ pub fn load_segment_to_memory( unsafe { core::ptr::copy_nonoverlapping(src, dst, file_size as usize); - if mem_size > file_size { core::ptr::write_bytes( dst.add(file_size as usize), diff --git a/kernel/src/driver/graphics/framebuffer.rs b/kernel/src/driver/graphics/framebuffer.rs index 7650bb4..5dacebb 100644 --- a/kernel/src/driver/graphics/framebuffer.rs +++ b/kernel/src/driver/graphics/framebuffer.rs @@ -1,5 +1,7 @@ use limine::framebuffer::Framebuffer as LimineFramebuffer; use spin::Mutex; +#[cfg(target_arch = "x86_64")] +use x86_64::structures::paging::OffsetPageTable; use crate::arch::arch::safe_lock; @@ -53,9 +55,19 @@ impl Framebuffer { } #[cfg(target_arch = "x86_64")] - pub fn setup_x86_64(&mut self) { - use crate::arch::arch::{FRAME_ALLOCATOR, HHDM_OFFSET}; - use x86_64::structures::paging::{FrameAllocator, PhysFrame, Size4KiB}; + pub fn setup_x86_64(&mut self, mapper: &mut OffsetPageTable) { + use crate::{ + arch::arch::{FRAME_ALLOCATOR, HHDM_OFFSET, serial_print}, + arch::x86_64::paging::initialize_paging_x86_64, + util::U64Buf, + }; + use x86_64::{ + PhysAddr, VirtAddr, + structures::paging::{ + FrameAllocator, Mapper, Page, PageTableFlags, PhysFrame, Size4KiB, + }, + }; + const KERNEL_FB_BASE: u64 = 0xffffffffa0000000; let buf_len = self.pitch * self.height; let byte_len = buf_len * core::mem::size_of::(); let pixel_frames = (byte_len + 4095) / 4096; @@ -65,8 +77,6 @@ impl Framebuffer { let struct_frame: PhysFrame = fa.allocate_frame().expect("framebuffer struct frame"); let struct_phys = struct_frame.start_address().as_u64(); - let hhdm_offset = HHDM_OFFSET.load(core::sync::atomic::Ordering::Relaxed); - let struct_virt = (struct_phys + hhdm_offset) as *mut UserFrameBuffer; let first_pixel_frame: PhysFrame = fa.allocate_frame().expect("framebuffer pixel frame 0"); @@ -74,7 +84,33 @@ impl Framebuffer { for _ in 1..pixel_frames { fa.allocate_frame().expect("framebuffer pixel frame"); } - let buf_virt_kernel = (buf_phys + hhdm_offset) as *mut u32; + + let hhdm_offset = HHDM_OFFSET.load(core::sync::atomic::Ordering::Relaxed); + + let flags = PageTableFlags::PRESENT | PageTableFlags::WRITABLE | PageTableFlags::NO_EXECUTE; + + let struct_page = Page::::containing_address(VirtAddr::new(KERNEL_FB_BASE)); + unsafe { + mapper + .map_to(struct_page, struct_frame, flags, &mut *fa) + .unwrap() + .flush(); + } + + for i in 0..pixel_frames { + let frame = PhysFrame::::containing_address(PhysAddr::new( + buf_phys + i as u64 * 4096, + )); + let page = Page::::containing_address(VirtAddr::new( + KERNEL_FB_BASE + 0x1000 + i as u64 * 4096, + )); + unsafe { + mapper.map_to(page, frame, flags, &mut *fa).unwrap().flush(); + } + } + + let struct_virt = KERNEL_FB_BASE as *mut UserFrameBuffer; + let buf_virt_kernel = (KERNEL_FB_BASE + 0x1000) as *mut u32; drop(fa); unsafe { core::ptr::write_bytes(buf_virt_kernel, 0, buf_len) }; diff --git a/kernel/src/driver/io/fs/assets.rs b/kernel/src/driver/io/fs/assets.rs new file mode 100644 index 0000000..4ef93a3 --- /dev/null +++ b/kernel/src/driver/io/fs/assets.rs @@ -0,0 +1,4 @@ +pub static INIT_ELF: &[u8] = include_bytes!("../../../../../assets/aarch64/init"); +pub static DOOM_WAD: &[u8] = include_bytes!("../../../../../assets/doom1.wad"); +pub static DOOM_ELF: &[u8] = include_bytes!("../../../../../assets/aarch64/doomgeneric"); +pub static HELLOWORLD_ELF: &[u8] = include_bytes!("../../../../../assets/aarch64/helloworld.elf"); diff --git a/kernel/src/driver/io/fs/mod.rs b/kernel/src/driver/io/fs/mod.rs index 10d397e..4fafc02 100644 --- a/kernel/src/driver/io/fs/mod.rs +++ b/kernel/src/driver/io/fs/mod.rs @@ -1 +1,2 @@ +pub mod assets; pub mod vfs; diff --git a/kernel/src/driver/io/fs/vfs.rs b/kernel/src/driver/io/fs/vfs.rs index ec06378..5cd8921 100644 --- a/kernel/src/driver/io/fs/vfs.rs +++ b/kernel/src/driver/io/fs/vfs.rs @@ -1,3 +1,4 @@ +use crate::driver::io::fs::assets::*; use core::ptr::{null, null_mut}; #[repr(C)] @@ -38,10 +39,6 @@ fn fd_ok(fd: Fd) -> bool { fd >= 0 && (fd as usize) < MAX_FD } -static DOOM_WAD: &[u8] = include_bytes!("../../../../../assets/doom1.wad"); -static DOOM_ELF: &[u8] = include_bytes!("../../../../../assets/doomgeneric"); -static HELLOWORLD_ELF: &[u8] = include_bytes!("../../../../../assets/helloworld.elf"); - static FILES: &[FakeFileEntry] = &[ FakeFileEntry { name: "testfile", diff --git a/kernel/src/driver/io/ps2.rs b/kernel/src/driver/io/ps2.rs index 18746f9..8159af0 100644 --- a/kernel/src/driver/io/ps2.rs +++ b/kernel/src/driver/io/ps2.rs @@ -14,6 +14,7 @@ use crate::arch::x86_64::kmi::{ }; use crate::{ driver::io::{keyboard::*, mouse::MOUSE}, + println, task::scheduler::SCHEDULER, util::get_bit, }; @@ -183,13 +184,14 @@ pub fn process_scancode(scancode: u8) -> Option { }; if let Some(linux_keycode) = keycode_to_linux(keycode) { + let effective_shift = kbd.get_modifiers().is_shifted() & kbd.get_modifiers().capslock; return Some(KeyboardEvent { state: if state == KeyState::Down { 1 } else { 0 }, _pad1: 0, key: linux_keycode as u16, mods: 0, _pad2: 0, - unicode, + unicode: keycode_to_char(linux_keycode, effective_shift).unwrap_or('\0') as u32, }); } else { return None; diff --git a/kernel/src/driver/io/virtio/input.rs b/kernel/src/driver/io/virtio/input.rs index 3e70cec..ff0d57e 100644 --- a/kernel/src/driver/io/virtio/input.rs +++ b/kernel/src/driver/io/virtio/input.rs @@ -196,18 +196,15 @@ pub fn input_interrupt(device_type: &str) { let event = unsafe { core::ptr::read_volatile(&queue.buffers[desc_idx as usize]) }; + handle_event(&event); + let avail_idx = unsafe { core::ptr::read_volatile(&queue.avail.idx) }; queue.avail.ring[(avail_idx as usize) % QUEUE_SIZE] = desc_idx as u16; core::sync::atomic::fence(core::sync::atomic::Ordering::SeqCst); - unsafe { core::ptr::write_volatile(&mut queue.avail.idx, avail_idx.wrapping_add(1)); } - - device.write(VirtioMmioReg::QueueNotify, 0); - - handle_event(&event); } } diff --git a/kernel/src/driver/io/virtio/mod.rs b/kernel/src/driver/io/virtio/mod.rs index 5c907ae..788ac0a 100644 --- a/kernel/src/driver/io/virtio/mod.rs +++ b/kernel/src/driver/io/virtio/mod.rs @@ -53,7 +53,7 @@ pub fn get_device(slot: u64) -> Option { Some(device) } -pub fn scan_devices() { +pub fn scan_virtio_devices() { for i in 0..VIRTIO_MMIO_COUNT { let base = VIRTIO_MMIO_BASE + i * VIRTIO_MMIO_STRIDE; let device = VirtioMmio::new(base); diff --git a/kernel/src/driver/serial.rs b/kernel/src/driver/serial.rs index 485965b..123cae0 100644 --- a/kernel/src/driver/serial.rs +++ b/kernel/src/driver/serial.rs @@ -1,4 +1,5 @@ use crate::alloc::string::ToString; +use crate::arch::arch::serial_print; use crate::driver::graphics::font_render::render_text; use crate::driver::graphics::framebuffer::Framebuffer; use crate::{arch::arch::safe_lock, driver::graphics::base::rgb}; @@ -14,6 +15,7 @@ pub struct ConsoleWriter<'a> { impl Write for ConsoleWriter<'_> { fn write_str(&mut self, s: &str) -> fmt::Result { + serial_print(s); self.console.print(s, self.fb); Ok(()) } diff --git a/kernel/src/main.rs b/kernel/src/main.rs index 03ea95d..3c1ba43 100644 --- a/kernel/src/main.rs +++ b/kernel/src/main.rs @@ -2,40 +2,42 @@ #![no_main] #![cfg_attr(target_arch = "x86_64", feature(abi_x86_interrupt))] #![feature(naked_functions_rustic_abi)] + extern crate alloc; + use core::fmt::Write; use core::sync::atomic::{AtomicU64, Ordering}; -#[cfg(target_arch = "aarch64")] -use crate::arch::aarch64::interrupts::enable_interrupts; +use limine::{ + BaseRevision, + request::{ + DateAtBootRequest, ExecutableAddressRequest, FramebufferRequest, HhdmRequest, + MemoryMapRequest, RequestsEndMarker, RequestsStartMarker, + }, +}; + #[cfg(target_arch = "aarch64")] use crate::arch::aarch64::paging::AArchPageTable; #[cfg(target_arch = "aarch64")] -use crate::driver::graphics::primitives::rectangle_filled; +use crate::driver::{graphics::primitives::rectangle_filled, io::virtio::input::init_keyboard}; #[cfg(target_arch = "aarch64")] use aarch64_cpu::registers::{DAIF, Writeable}; -#[cfg(target_arch = "aarch64")] -use crate::driver::io::virtio::input::init_keyboard; - -#[cfg(target_arch = "x86_64")] -use crate::driver::elf::loader::run_elf; #[cfg(target_arch = "x86_64")] use crate::driver::io::ps2::init_keyboard; use crate::arch::arch::{HHDM_OFFSET, infinite_idle, init, kernel_crash, serial_print}; - -use crate::driver::graphics::base::rgb; -use crate::driver::graphics::framebuffer::{init_framebuffer, with_framebuffer}; - -use crate::driver::serial::{ConsoleWriter, init_serial_console, with_serial_console}; -use crate::driver::timer::TIMER; - -use limine::BaseRevision; -use limine::request::{ - DateAtBootRequest, ExecutableAddressRequest, FramebufferRequest, HhdmRequest, MemoryMapRequest, - RequestsEndMarker, RequestsStartMarker, +use crate::driver::{ + elf::loader::run_elf, + graphics::{ + base::rgb, + framebuffer::{init_framebuffer, with_framebuffer}, + }, + io::fs::assets::INIT_ELF, + serial::{ConsoleWriter, init_serial_console, with_serial_console}, + timer::TIMER, }; + pub mod arch; pub mod config; pub mod driver; @@ -43,14 +45,6 @@ pub mod mm; pub mod task; pub mod util; -#[repr(C, align(16))] -#[allow(dead_code)] -struct AlignedElf([u8; include_bytes!("../../assets/init").len()]); -#[allow(dead_code)] -static INIT_ELF: AlignedElf = AlignedElf(*include_bytes!("../../assets/init")); -#[allow(dead_code)] -static INIT_ELF_BYTES: &[u8] = &INIT_ELF.0; - /// Sets the base revision to the latest revision supported by the crate. /// See specification for further info. /// Be sure to mark all limine requests with #[used], otherwise they may be removed by the compiler. @@ -200,13 +194,9 @@ pub unsafe extern "C" fn kernel_main_aarch64(mapper: &mut AArchPageTable) -> ! { println!("Could not get date at boot. Will default to 0.") } - println!("Hello from Aarch64!"); - with_framebuffer(|fb| { - with_serial_console(|sc| sc.render(fb)); - rectangle_filled(fb, 100, 100, 20, 20, rgb(255, 255, 255)); - }); + DAIF.write(DAIF::D::Masked + DAIF::A::Masked + DAIF::I::Unmasked + DAIF::F::Masked); - enable_interrupts(); + run_elf(INIT_ELF, false, true); loop {} } @@ -217,20 +207,24 @@ pub unsafe fn kernel_main_x86_64() -> ! { // removed by the linker. assert!(BASE_REVISION.is_supported()); - if let Some(hhdm_response) = HHDM_REQUEST.get_response() { - if let Some(memory_map_response) = MEMORY_MAP_REQUEST.get_response() { - init(hhdm_response, memory_map_response); + let (hhdm_response, memory_map_response) = { + if let Some(a) = HHDM_REQUEST.get_response() { + if let Some(b) = MEMORY_MAP_REQUEST.get_response() { + (a, b) + } else { + kernel_crash(); // Could not get required info from Limine's memory map. + } } else { - kernel_crash(); // Could not get required info from Limine's memory map. + kernel_crash(); // Could not get required info from Limine's higher-half direct mapping. } - } else { - kernel_crash(); // Could not get required info from Limine's higher-half direct mapping. - } + }; + + let mut mapper = init(hhdm_response, memory_map_response); if let Some(framebuffer_response) = FRAMEBUFFER_REQUEST.get_response() { if let Some(limine_framebuffer) = framebuffer_response.framebuffers().next() { init_framebuffer(&limine_framebuffer); - with_framebuffer(|fb| fb.setup_x86_64()); + with_framebuffer(|fb| fb.setup_x86_64(&mut mapper)); } else { serial_print("no framebuffers found"); } @@ -246,7 +240,7 @@ pub unsafe fn kernel_main_x86_64() -> ! { println!("Could not get date at boot. Will default to 0.") } - run_elf(INIT_ELF_BYTES, false); + run_elf(INIT_ELF, false, true); loop {} } @@ -276,6 +270,12 @@ impl core::fmt::Write for BufWriter<'_> { #[panic_handler] fn rust_panic(_info: &core::panic::PanicInfo) -> ! { serial_print("\nKERNEL PANIC:\n"); + serial_print( + _info + .message() + .as_str() + .unwrap_or("Could not get message str"), + ); let mut buf = [0u8; 512]; let msg = { let mut w = BufWriter::new(&mut buf); diff --git a/kernel/src/task/context.rs b/kernel/src/task/context.rs index 61af5fa..89fca13 100644 --- a/kernel/src/task/context.rs +++ b/kernel/src/task/context.rs @@ -62,7 +62,7 @@ pub struct UserContext { pub spsr_el1: u64, pub esr_el1: u64, // exception type pub far_el1: u64, // fault type - _pad: u64, + pub sp_el0: u64, } #[unsafe(no_mangle)] diff --git a/kernel/src/task/scheduler.rs b/kernel/src/task/scheduler.rs index da8dc92..5d8d374 100644 --- a/kernel/src/task/scheduler.rs +++ b/kernel/src/task/scheduler.rs @@ -4,13 +4,16 @@ use alloc::{collections::btree_map::BTreeMap, vec::Vec}; use crate::{ arch::arch::{enter_usermode, safe_lock}, - task::{ - context::UserContext, - process::{Process, ProcessState}, - }, + task::context::UserContext, + task::process::{Process, ProcessState}, util::Locked, }; +#[cfg(target_arch = "aarch64")] +use crate::arch::aarch64::interrupts::run_next; +#[cfg(target_arch = "x86_64")] +use crate::arch::x86_64::syscall::run_next; + pub static CURRENT_PID: AtomicU64 = AtomicU64::new(0); #[inline] @@ -119,9 +122,20 @@ impl Locked { #[allow(unused_variables, unused_unsafe)] Some(saved_ctx) => unsafe { #[cfg(target_arch = "x86_64")] - run_next((&saved_ctx) as *const UserContext, saved_ctx.rsp) + run_next((&saved_ctx) as *const UserContext, saved_ctx.rsp); + #[cfg(target_arch = "aarch64")] + run_next((&saved_ctx) as *const UserContext, saved_ctx.sp_el0); }, - None => enter_usermode(entry as u64, (stack_top & !0xF) - 8, should_swapgs), + None => enter_usermode( + entry as u64, + (stack_top & !0xF) + - cfg_select! { + target_arch = "x86_64" => 8, + target_arch = "aarch64" => 16, + _ => 8 + }, + should_swapgs, + ), } } @@ -136,39 +150,3 @@ impl Locked { } pub static SCHEDULER: Locked = Locked::new(Scheduler::new()); - -#[cfg(target_arch = "x86_64")] -#[unsafe(naked)] -#[unsafe(no_mangle)] -unsafe fn run_next(ctx: *const UserContext, user_rsp: u64) { - core::arch::naked_asm!( - "mov gs:[0], rsi", // store new user rsp - "mov rsp, rdi", - "mov r15, qword ptr [rsp + 0]", - "mov r14, qword ptr [rsp + 8]", - "mov r13, qword ptr [rsp + 16]", - "mov r12, qword ptr [rsp + 24]", - "mov r11, qword ptr [rsp + 32]", // rflags - "mov r10, qword ptr [rsp + 40]", - "mov r9, qword ptr [rsp + 48]", - "mov r8, qword ptr [rsp + 56]", - "mov rsi, qword ptr [rsp + 64]", - "mov rdi, qword ptr [rsp + 72]", - "mov rbp, qword ptr [rsp + 80]", - "mov rdx, qword ptr [rsp + 88]", - "mov rcx, qword ptr [rsp + 96]", // rip - "mov rbx, qword ptr [rsp + 104]", - "mov rax, qword ptr [rsp + 112]", - "mov rsp, qword ptr [rsp + 120]", // user rsp - "swapgs", - "sysretq", - ); -} - -#[cfg(target_arch = "aarch64")] -#[unsafe(naked)] -#[unsafe(no_mangle)] -unsafe fn run_next(ctx: *const UserContext, user_rsp: u64) { - // TODO: add switching logic - core::arch::naked_asm!("udf #0"); -} diff --git a/user/apps/doomgeneric b/user/apps/doomgeneric index 2c34740..6ce96f7 160000 --- a/user/apps/doomgeneric +++ b/user/apps/doomgeneric @@ -1 +1 @@ -Subproject commit 2c34740743d46ed4847406be50ab65ad40f55363 +Subproject commit 6ce96f770ee7290204245056f3d0a9f87cda1f6f diff --git a/user/apps/helloworld/compile.sh b/user/apps/helloworld/compile.sh index c8c7120..4033297 100644 --- a/user/apps/helloworld/compile.sh +++ b/user/apps/helloworld/compile.sh @@ -1,3 +1,15 @@ GCC_INCLUDES=$(gcc -print-file-name=include) SYS_INCLUDES=/usr/include -gcc -w -static -D__NO_INLINE__ -O0 -mno-mmx -mno-avx -fno-stack-protector -fno-inline -fno-inline-small-functions -fno-indirect-inlining -fno-builtin -fcompare-debug-second -nostdlib -nostdinc helloworld.c -Wl,--gc-sections -L../../libxunil/target/release -l:libxunil.a -I../../libxunil/include -I"$GCC_INCLUDES" -I"$SYS_INCLUDES" -o ../../../assets/helloworld.elf + +if [ "$KARCH" = "aarch64" ]; then + CC="aarch64-linux-gnu-gcc" + ARCH_FLAGS="-march=armv8-a+nosimd -mabi=lp64" +elif [ "$KARCH" = "x86_64" ]; then + CC="x86_64-linux-gnu-gcc" + ARCH_FLAGS="-m64 -mno-mmx -mno-avx" +else + echo "Error: Unsupported KARCH: $KARCH" + exit 1 +fi + +$CC -w -static -D__NO_INLINE__ -O3 $ARCH_FLAGS -fno-stack-protector -fno-inline -fno-inline-small-functions -fno-indirect-inlining -fno-builtin -fcompare-debug-second -nostdlib -nostdinc helloworld.c -Wl,--gc-sections -L../../libxunil/target/$KARCH-unknown-none/release -l:libxunil.a -I../../libxunil/include -I"$GCC_INCLUDES" -I"$SYS_INCLUDES" -o ../../../assets/$KARCH/helloworld.elf diff --git a/user/init b/user/init index 601d2ca..417af31 160000 --- a/user/init +++ b/user/init @@ -1 +1 @@ -Subproject commit 601d2cab7f2556d4a4aad24e35c9e33542289dda +Subproject commit 417af31481b2be5c78ff6ca2955ea085d2d07316 diff --git a/user/libxunil b/user/libxunil index 7ddebd6..6025f75 160000 --- a/user/libxunil +++ b/user/libxunil @@ -1 +1 @@ -Subproject commit 7ddebd6df5b9090a6ba02e951e1317cdba5c4583 +Subproject commit 6025f75ab3c295b7f178429349c67457511ec3b9