Quellcode durchsuchen

feat: add compilation option for riscv64, fix x86 compile

greatbridf vor 7 Monaten
Ursprung
Commit
353fe877ea

+ 0 - 1
.cargo/config.toml

@@ -1,5 +1,4 @@
 [build]
-# target = 'x86_64-unknown-none.json'
 target = "riscv64gc-unknown-none-elf"
 target-dir = 'build'
 

+ 28 - 0
.vscode/launch.json

@@ -28,6 +28,34 @@
             "preLaunchTask": "debug run riscv64",
             "postDebugTask": "kill qemu riscv64"
         },
+        {
+            "type": "cppdbg",
+            "request": "launch",
+            "name": "Launch Kernel (x86_64)",
+            "program": "${workspaceFolder}/build/kernel.sym",
+            "args": [],
+            "stopAtEntry": false,
+            "cwd": "${workspaceFolder}",
+            "environment": [],
+            "externalConsole": false,
+            "MIMode": "gdb",
+            "miDebuggerPath": "x86_64-elf-gdb",
+            "miDebuggerServerAddress": "127.0.0.1:1234",
+            "setupCommands": [
+                {
+                    "text": "-enable-pretty-printing",
+                    "description": "Enable GDB pretty printing",
+                    "ignoreFailures": true
+                },
+                // {
+                //     "text": "source ${workspaceFolder}/pretty-print.py",
+                //     "description": "Load GDB pretty printers",
+                //     "ignoreFailures": false
+                // },
+            ],
+            "preLaunchTask": "debug run x86_64",
+            "postDebugTask": "kill qemu x86_64"
+        },
         {
             "type": "cppdbg",
             "request": "launch",

+ 41 - 12
Makefile.src

@@ -7,10 +7,14 @@ QEMU ?= ##QEMU##
 GDB ?= ##GDB##
 FDISK ?= ##FDISK##
 
-QEMU_ARGS ?= -machine q35 -drive id=disk,file=build/boot.img,format=raw,if=none \
-	-device ahci,id=ahci -device ide-hd,drive=disk,bus=ahci.0 \
-	-netdev user,id=mynet0,net=192.168.1.0/24,dhcpstart=192.168.1.16 -device e1000e,netdev=mynet0 \
-	-no-reboot -no-shutdown
+COMMA := ,
+
+ifeq ($(MODE),debug)
+MODE := dev
+endif
+
+QEMU_ARGS ?= -no-reboot -no-shutdown
+CARGO_FLAGS := --profile $(MODE) --features $(FEATURES)$(if $(SMP),$(COMMA)smp,)
 
 ifeq ($(HOST),darwin)
 QEMU_ACCEL ?= -accel tcg
@@ -28,13 +32,38 @@ ifneq ($(SMP),)
 QEMU_ARGS += -smp $(SMP)
 endif
 
-ifeq ($(MODE),debug)
-MODE := dev
-endif
+ifeq ($(ARCH),riscv64)
 
-COMMA := ,
+QEMU_ARGS += \
+	-machine virt -kernel build/riscv64gc-unknown-none-elf/debug/eonix_kernel \
+	-device virtio-blk-device,drive=disk0,bus=virtio-mmio-bus.0 \
+	-device virtio-blk-device,drive=disk1,bus=virtio-mmio-bus.1 \
+	-device virtio-net-device,netdev=mynet0 \
+	-drive id=disk0,file=build/boot.img,format=raw,if=none \
+	-drive id=disk1,file=build/fs.img,format=raw,if=none \
+	-netdev user,id=mynet0 \
+	-rtc base=utc
 
-CARGO_FLAGS := --profile $(MODE) --features $(FEATURES)$(if $(SMP),$(COMMA)smp,)
+CARGO_FLAGS += --target riscv64gc-unknown-none-elf
+
+.PHONY: run
+run: kernel build/kernel.sym build/boot.img
+	$(QEMU) $(QEMU_ARGS) -display none -serial mon:stdio
+
+.PHONY: srun
+srun: kernel build/kernel.sym build/boot.img
+	$(QEMU) $(QEMU_ARGS) -display none -S -s -serial mon:stdio
+
+else ifeq ($(ARCH),x86_64)
+
+QEMU_ARGS += \
+	-machine q35 \
+	-device ahci,id=ahci -device ide-hd,drive=disk,bus=ahci.0 \
+	-device e1000e,netdev=mynet0 \
+	-drive id=disk,file=build/boot.img,format=raw,if=none \
+	-netdev user,id=mynet0
+
+CARGO_FLAGS += --target x86_64-unknown-none.json
 
 .PHONY: run
 run: build
@@ -44,12 +73,12 @@ run: build
 srun: build
 	$(QEMU) $(QEMU_ARGS) -display none -S -s -serial mon:stdio
 
+endif
+
 .PHONY: clean
 clean:
-	-mv build/fs.img .
 	-rm -rf build
 	-mkdir build
-	-mv fs.img build
 
 .PHONY: clean-all
 clean-all: clean
@@ -92,7 +121,7 @@ build/kernel.bin: kernel
 	cargo objcopy $(CARGO_FLAGS) -- -O binary --strip-debug \
 		-R .mbr -R .stage1 build/kernel.bin
 
-build/fs.img: init_script.sh
+build/fs.img: init_script.sh script/build-img.sh
 	sh script/build-img.sh
 
 build/boot.img: build/mbr.bin build/stage1.bin build/kernel.bin build/fs.img

+ 6 - 0
crates/eonix_hal/src/arch/riscv64/memory.x

@@ -13,4 +13,10 @@ REGION_ALIAS("REGION_DATA", KIMAGE);
 REGION_ALIAS("REGION_BSS", KBSS);
 REGION_ALIAS("REGION_EHFRAME", KIMAGE);
 
+REGION_ALIAS("LINK_REGION_TEXT", RAM);
+REGION_ALIAS("LINK_REGION_RODATA", RAM);
+REGION_ALIAS("LINK_REGION_DATA", RAM);
+REGION_ALIAS("LINK_REGION_BSS", RAM);
+REGION_ALIAS("LINK_REGION_EHFRAME", RAM);
+
 _stext = ORIGIN(REGION_TEXT) + LOADADDR(.text) - ORIGIN(RAM);

+ 7 - 3
crates/eonix_hal/src/arch/riscv64/trap/mod.rs

@@ -6,7 +6,10 @@ use core::arch::{global_asm, naked_asm};
 use core::mem::{offset_of, size_of};
 use core::num::NonZero;
 use core::ptr::NonNull;
-use eonix_hal_traits::{context::RawTaskContext, trap::TrapReturn};
+use eonix_hal_traits::{
+    context::RawTaskContext,
+    trap::{IrqState as IrqStateTrait, TrapReturn},
+};
 use riscv::register::sie::Sie;
 use riscv::register::stvec::TrapMode;
 use riscv::register::{scause, sepc, stval};
@@ -281,9 +284,10 @@ impl IrqState {
     pub fn save() -> Self {
         IrqState(sie::read())
     }
+}
 
-    #[inline]
-    pub fn restore(self) {
+impl IrqStateTrait for IrqState {
+    fn restore(self) {
         let Self(state) = self;
         unsafe {
             sie::write(state);

+ 1 - 1
crates/eonix_hal/src/arch/x86_64/bootstrap/init.rs

@@ -241,7 +241,7 @@ fn bootstrap_smp(alloc: impl Allocator, page_alloc: &RefCell<BasicPageAlloc>) {
         let stack_range = {
             let page_alloc = BasicPageAllocRef::new(&page_alloc);
 
-            let ap_stack = Page::alloc_order_in(3, page_alloc);
+            let ap_stack = Page::alloc_order_in(4, page_alloc);
             let stack_range = ap_stack.range();
             ap_stack.into_raw();
 

+ 0 - 1
crates/eonix_hal/src/arch/x86_64/link.x

@@ -76,7 +76,6 @@ SECTIONS {
     {
         __spercpu = .;
 
-        PERCPU_START = .;
         QUAD(0); /* Reserved for x86 percpu pointer */
 
         . = ALIGN(16);

+ 6 - 0
crates/eonix_hal/src/arch/x86_64/memory.x

@@ -9,3 +9,9 @@ REGION_ALIAS("REGION_RODATA", KIMAGE);
 REGION_ALIAS("REGION_DATA", KIMAGE);
 REGION_ALIAS("REGION_BSS", KBSS);
 REGION_ALIAS("REGION_EHFRAME", KIMAGE);
+
+REGION_ALIAS("LINK_REGION_TEXT", KIMAGE);
+REGION_ALIAS("LINK_REGION_RODATA", KIMAGE);
+REGION_ALIAS("LINK_REGION_DATA", KIMAGE);
+REGION_ALIAS("LINK_REGION_BSS", KBSS);
+REGION_ALIAS("LINK_REGION_EHFRAME", KIMAGE);

+ 7 - 6
crates/eonix_hal/src/arch/x86_64/trap.rs

@@ -329,17 +329,18 @@ unsafe extern "C" fn captured_trap_return(trap_context: usize) -> ! {
 }
 
 impl TrapReturn for TrapContext {
-    unsafe fn trap_return(&mut self) {
+    type TaskContext = TaskContext;
+
+    unsafe fn trap_return(&mut self, task_ctx: &mut Self::TaskContext) {
         let irq_states = disable_irqs_save();
         let old_handler = TRAP_HANDLER.swap(captured_trap_handler);
 
-        let mut to_ctx = TaskContext::new();
-        to_ctx.set_program_counter(captured_trap_return as _);
-        to_ctx.set_stack_pointer(&raw mut *self as usize);
-        to_ctx.set_interrupt_enabled(false);
+        task_ctx.set_program_counter(captured_trap_return as _);
+        task_ctx.set_stack_pointer(&raw mut *self as usize);
+        task_ctx.set_interrupt_enabled(false);
 
         unsafe {
-            TaskContext::switch(CAPTURER_CONTEXT.as_mut(), &mut to_ctx);
+            TaskContext::switch(CAPTURER_CONTEXT.as_mut(), &mut *task_ctx);
         }
 
         TRAP_HANDLER.set(old_handler);

+ 0 - 3
crates/eonix_hal/src/arch/x86_64/trap/trap_context.rs

@@ -37,9 +37,6 @@ impl TrapContext {
             13 => Fault::BadAccess,
             14 => {
                 let mut error_code = PageFaultErrorCode::empty();
-                if self.errcode & 1 == 0 {
-                    error_code |= PageFaultErrorCode::NonPresent;
-                }
 
                 if self.errcode & 2 != 0 {
                     error_code |= PageFaultErrorCode::Write;

+ 5 - 5
crates/eonix_hal/src/link.x.in

@@ -9,7 +9,7 @@ SECTIONS {
         *(.text.entry);
         *(.text .text.*);
 
-    } > REGION_TEXT AT> RAM
+    } > REGION_TEXT AT> LINK_REGION_TEXT
 
     __etext = .;
 
@@ -19,7 +19,7 @@ SECTIONS {
 
         *(.rodata .rodata.*);
 
-    } > REGION_RODATA AT> RAM
+    } > REGION_RODATA AT> LINK_REGION_RODATA
 
     __erodata = .;
 
@@ -30,7 +30,7 @@ SECTIONS {
         *(.data .data.*);
         *(.got .got.plt);
 
-    } > REGION_DATA AT> RAM
+    } > REGION_DATA AT> LINK_REGION_DATA
 
     __edata = .;
 
@@ -41,7 +41,7 @@ SECTIONS {
         *(.bss .bss.*);
 
         . = ALIGN(0x1000);
-    } > REGION_BSS AT> RAM
+    } > REGION_BSS AT> LINK_REGION_BSS
 
     __ebss = .;
 
@@ -51,7 +51,7 @@ SECTIONS {
 
         KEEP(*(.eh_frame .eh_frame*));
 
-    } > REGION_EHFRAME AT> RAM
+    } > REGION_EHFRAME AT> LINK_REGION_EHFRAME
 
     . = ALIGN(0x1000);
     __eeh_frame = .;

+ 1 - 0
crates/eonix_sync/eonix_sync_rt/src/spin_irq.rs

@@ -1,3 +1,4 @@
+use eonix_hal::traits::trap::IrqState as _;
 use eonix_hal::trap::{disable_irqs_save, IrqState};
 use eonix_spin::{ContextUnlock, Spin, SpinContext, SpinGuard, UnlockedContext};
 use eonix_sync_base::Relax;

+ 11 - 6
src/kernel/interrupt.rs

@@ -22,13 +22,18 @@ pub fn default_irq_handler(irqno: usize) {
         handler();
     }
 
-    // const PIC1_COMMAND: Port8 = Port8::new(0x20);
-    // const PIC2_COMMAND: Port8 = Port8::new(0xA0);
+    #[cfg(target_arch = "x86_64")]
+    {
+        use crate::driver::Port8;
 
-    // PIC1_COMMAND.write(0x20); // EOI
-    // if irqno >= 8 {
-    //     PIC2_COMMAND.write(0x20); // EOI
-    // }
+        const PIC1_COMMAND: Port8 = Port8::new(0x20);
+        const PIC2_COMMAND: Port8 = Port8::new(0xA0);
+
+        PIC1_COMMAND.write(0x20); // EOI
+        if irqno >= 8 {
+            PIC2_COMMAND.write(0x20); // EOI
+        }
+    }
 }
 
 pub fn default_fault_handler(fault_type: Fault, trap_ctx: &mut TrapContext) {

+ 4 - 3
src/kernel/mem/mm_list/page_fault.rs

@@ -1,8 +1,7 @@
 use super::{MMList, VAddr};
 use crate::kernel::task::{Signal, Thread};
-use arch::flush_tlb;
 use eonix_hal::traits::fault::PageFaultErrorCode;
-use eonix_mm::address::{Addr as _, AddrOps as _, VRange};
+use eonix_mm::address::{AddrOps as _, VRange};
 use eonix_mm::paging::PAGE_SIZE;
 use eonix_runtime::task::Task;
 
@@ -23,6 +22,7 @@ impl FixEntry {
         VAddr::from((self.start + self.length) as usize)
     }
 
+    #[allow(dead_code)]
     fn range(&self) -> VRange {
         VRange::new(self.start(), self.end())
     }
@@ -85,10 +85,11 @@ impl MMList {
 
         #[cfg(not(target_arch = "x86_64"))]
         {
+            use eonix_mm::address::Addr as _;
             // Flush the TLB for the affected address range.
             // x86 CPUs will try to retrieve the PTE again for non-present entries.
             // So we don't need to flush TLB.
-            flush_tlb(addr.floor().addr());
+            arch::flush_tlb(addr.floor().addr());
         }
 
         Ok(())

+ 3 - 1
src/kernel/pcie/driver.rs

@@ -28,7 +28,9 @@ pub fn register_driver(driver: impl PCIDriver + 'static) -> KResult<()> {
         btree_map::Entry::Occupied(_) => Err(EEXIST)?,
     };
 
-    if let Some(device) = PCIE_DEVICES.lock().find(&index).clone_pointer() {
+    let device = PCIE_DEVICES.lock().find(&index).clone_pointer();
+
+    if let Some(device) = device {
         driver.handle_device(device)?;
     };
 

+ 6 - 6
src/kernel/pcie/init.rs

@@ -2,13 +2,9 @@ use super::{
     device::{PCIDevice, SegmentGroup, PCIE_DEVICES},
     error::PciError,
 };
-use crate::kernel::{
-    constants::{EINVAL, ENOENT},
-    mem::PhysAccess as _,
-};
+use crate::kernel::mem::PhysAccess as _;
 use acpi::{AcpiHandler, PhysicalMapping};
-use eonix_hal::device::FDT;
-use eonix_mm::address::{PAddr, PRange};
+use eonix_mm::address::PAddr;
 
 #[derive(Clone)]
 struct AcpiHandlerImpl;
@@ -56,6 +52,10 @@ pub fn init_pcie() -> Result<(), PciError> {
 
     #[cfg(target_arch = "riscv64")]
     {
+        use crate::kernel::constants::{EINVAL, ENOENT};
+        use eonix_hal::device::FDT;
+        use eonix_mm::address::PRange;
+
         let pcie_node = FDT.find_node("/soc/pci").ok_or(ENOENT)?;
         let bus_range = pcie_node.property("bus-range").ok_or(ENOENT)?;
         let reg = pcie_node.reg().ok_or(EINVAL)?.next().ok_or(EINVAL)?;

+ 1 - 0
src/kernel/syscall/file_rw.rs

@@ -125,6 +125,7 @@ fn getdents64(fd: u32, buffer: *mut u8, bufsize: usize) -> KResult<usize> {
     Ok(buffer.wrote())
 }
 
+#[cfg(not(target_arch = "x86_64"))]
 #[eonix_macros::define_syscall(SYS_NEWFSTATAT)]
 fn newfstatat(dirfd: u32, pathname: *const u8, statbuf: *mut Stat, flags: u32) -> KResult<()> {
     let dentry = if (flags & AT_EMPTY_PATH) != 0 {

+ 1 - 1
src/kernel/syscall/mm.rs

@@ -118,7 +118,7 @@ fn mmap2(
     fd: u32,
     pgoffset: usize,
 ) -> KResult<usize> {
-    do_mmap2(addr, len, prot, flags, fd, pgoffset)
+    do_mmap2(thread, addr, len, prot, flags, fd, pgoffset)
 }
 
 #[eonix_macros::define_syscall(SYS_MUNMAP)]

+ 29 - 3
src/kernel/syscall/procops.rs

@@ -279,7 +279,12 @@ fn wait4(waitpid: u32, arg1: *mut u32, options: u32, rusage: *mut RUsage) -> KRe
         WaitInfo::None
     };
 
-    do_waitid(thread, P_PID, waitpid, waitinfo, options, rusage)
+    let idtype = match waitpid {
+        u32::MAX => P_ALL,
+        _ => P_PID,
+    };
+
+    do_waitid(thread, idtype, waitpid, waitinfo, options, rusage)
 }
 
 #[cfg(target_arch = "x86_64")]
@@ -342,12 +347,33 @@ fn getppid() -> KResult<u32> {
     Ok(thread.process.parent_rcu().map_or(0, |x| x.pid))
 }
 
-#[eonix_macros::define_syscall(SYS_GETUID)]
-fn getuid() -> KResult<u32> {
+fn do_geteuid(_thread: &Thread) -> KResult<u32> {
     // All users are root for now.
     Ok(0)
 }
 
+fn do_getuid(_thread: &Thread) -> KResult<u32> {
+    // All users are root for now.
+    Ok(0)
+}
+
+#[cfg(target_arch = "x86_64")]
+#[eonix_macros::define_syscall(SYS_GETUID32)]
+fn getuid32() -> KResult<u32> {
+    do_getuid(thread)
+}
+
+#[eonix_macros::define_syscall(SYS_GETUID)]
+fn getuid() -> KResult<u32> {
+    do_getuid(thread)
+}
+
+#[cfg(target_arch = "x86_64")]
+#[eonix_macros::define_syscall(SYS_GETEUID32)]
+fn geteuid32() -> KResult<u32> {
+    do_geteuid(thread)
+}
+
 #[eonix_macros::define_syscall(SYS_GETEUID)]
 fn geteuid() -> KResult<u32> {
     // All users are root for now.

+ 1 - 1
src/kernel/task/thread.rs

@@ -28,7 +28,7 @@ use eonix_hal::{
     traits::{
         fault::Fault,
         fpu::RawFpuState as _,
-        trap::{RawTrapContext, TrapReturn, TrapType},
+        trap::{IrqState as _, RawTrapContext, TrapReturn, TrapType},
     },
     trap::{disable_irqs_save, TrapContext},
 };

+ 23 - 4
src/lib.rs

@@ -25,7 +25,7 @@ use core::{
     hint::spin_loop,
     sync::atomic::{AtomicBool, Ordering},
 };
-use eonix_hal::{processor::CPU, trap::disable_irqs_save};
+use eonix_hal::{processor::CPU, traits::trap::IrqState, trap::disable_irqs_save};
 use eonix_mm::address::PRange;
 use eonix_runtime::{run::FutureRun, scheduler::Scheduler, task::Task};
 use kernel::{
@@ -159,11 +159,30 @@ async fn init_process(early_kstack: PRange) {
         )
         .unwrap();
 
-        let init = Dentry::open(fs_context, Path::new(b"/mnt/busybox").unwrap(), true)
-            .expect("busybox should be present in /mnt");
+        let init_names = [
+            &b"/sbin/init"[..],
+            &b"/init"[..],
+            &b"/bin/busybox"[..],
+            &b"/mnt/busybox"[..],
+        ];
+
+        let mut init_name = None;
+        let mut init = None;
+        for name in &init_names {
+            if let Ok(dentry) = Dentry::open(fs_context, Path::new(name).unwrap(), true) {
+                if dentry.is_valid() {
+                    init_name = Some(*name);
+                    init = Some(dentry);
+                    break;
+                }
+            }
+        }
+
+        let init = init.expect("No init binary found in the system.");
+        let init_name = init_name.unwrap();
 
         let argv = vec![
-            CString::new("/mnt/busybox").unwrap(),
+            CString::new(init_name).unwrap(),
             CString::new("sh").unwrap(),
             CString::new("/mnt/initsh").unwrap(),
         ];