Преглед на файлове

partial work: fix riscv64 bootstrap

greatbridf преди 7 месеца
родител
ревизия
4351cf5573
променени са 47 файла, в които са добавени 495 реда и са изтрити 2859 реда
  1. 6 6
      .vscode/launch.json
  2. 1 1
      .vscode/tasks.json
  3. 28 3
      Cargo.lock
  4. 3 0
      Cargo.toml
  5. 38 2
      arch/arch_macros/src/riscv64/percpu.rs
  6. 8 0
      arch/arch_macros/src/x86_64/percpu.rs
  7. 0 69
      arch/src/riscv64/config.rs
  8. 0 16
      arch/src/riscv64/console.rs
  9. 0 178
      arch/src/riscv64/context.rs
  10. 0 67
      arch/src/riscv64/entry/mod.rs
  11. 0 238
      arch/src/riscv64/entry/page.rs
  12. 0 99
      arch/src/riscv64/fdt.rs
  13. 0 145
      arch/src/riscv64/init.rs
  14. 0 62
      arch/src/riscv64/interrupt/clint.rs
  15. 0 319
      arch/src/riscv64/interrupt/context.rs
  16. 0 161
      arch/src/riscv64/interrupt/mod.rs
  17. 0 137
      arch/src/riscv64/interrupt/plic.rs
  18. 0 139
      arch/src/riscv64/interrupt/trap.S
  19. 0 32
      arch/src/riscv64/interrupt/trap.rs
  20. 0 50
      arch/src/riscv64/io.rs
  21. 0 170
      arch/src/riscv64/kernel.ld
  22. 0 214
      arch/src/riscv64/mm.rs
  23. 10 12
      arch/src/riscv64/mod.rs
  24. 1 1
      crates/eonix_hal/Cargo.toml
  25. 85 75
      crates/eonix_hal/src/arch/riscv64/bootstrap.rs
  26. 4 27
      crates/eonix_hal/src/arch/riscv64/config.rs
  27. 12 29
      crates/eonix_hal/src/arch/riscv64/context.rs
  28. 16 114
      crates/eonix_hal/src/arch/riscv64/cpu.rs
  29. 51 29
      crates/eonix_hal/src/arch/riscv64/fdt.rs
  30. 0 62
      crates/eonix_hal/src/arch/riscv64/interrupt/clint.rs
  31. 24 63
      crates/eonix_hal/src/arch/riscv64/interrupt/mod.rs
  32. 0 137
      crates/eonix_hal/src/arch/riscv64/interrupt/plic.rs
  33. 21 16
      crates/eonix_hal/src/arch/riscv64/link.x
  34. 3 4
      crates/eonix_hal/src/arch/riscv64/memory.x
  35. 57 55
      crates/eonix_hal/src/arch/riscv64/mm.rs
  36. 4 7
      crates/eonix_hal/src/arch/riscv64/mod.rs
  37. 37 42
      crates/eonix_hal/src/arch/riscv64/trap/mod.rs
  38. 34 51
      crates/eonix_hal/src/arch/riscv64/trap/trap_context.rs
  39. 5 0
      crates/eonix_hal/src/bootstrap.rs
  40. 7 0
      crates/eonix_hal/src/device.rs
  41. 1 0
      crates/eonix_hal/src/lib.rs
  42. 6 16
      crates/eonix_hal/src/link.x.in
  43. 5 1
      crates/eonix_percpu/eonix_percpu_macros/src/lib.rs
  44. 2 1
      crates/eonix_runtime/src/task.rs
  45. 0 1
      crates/eonix_sync/eonix_sync_rt/src/spin_irq.rs
  46. 0 1
      src/kernel_init.rs
  47. 26 7
      src/lib.rs

+ 6 - 6
.vscode/launch.json

@@ -11,7 +11,7 @@
             "environment": [],
             "externalConsole": false,
             "MIMode": "gdb",
-            "miDebuggerPath": "x86_64-elf-gdb",
+            "miDebuggerPath": "/Users/david/.local/riscv64-unknown-elf-gcc-8.3.0-2020.04.1-x86_64-apple-darwin/bin/riscv64-unknown-elf-gdb",
             "miDebuggerServerAddress": "127.0.0.1:1234",
             "setupCommands": [
                 // {
@@ -24,11 +24,11 @@
                     "description": "Enable GDB pretty printing",
                     "ignoreFailures": true
                 },
-                {
-                    "text": "source ${workspaceFolder}/pretty-print.py",
-                    "description": "Load GDB pretty printers",
-                    "ignoreFailures": false
-                },
+                // {
+                //     "text": "source ${workspaceFolder}/pretty-print.py",
+                //     "description": "Load GDB pretty printers",
+                //     "ignoreFailures": false
+                // },
             ],
             "preLaunchTask": "debug run",
             "postDebugTask": "kill qemu"

+ 1 - 1
.vscode/tasks.json

@@ -46,7 +46,7 @@
         {
             "label": "kill qemu",
             "type": "shell",
-            "command": "killall qemu-system-x86_64",
+            "command": "killall qemu-system-riscv64",
             "presentation": {
                 "echo": false,
                 "reveal": "never",

+ 28 - 3
Cargo.lock

@@ -22,7 +22,7 @@ dependencies = [
  "eonix_hal_traits",
  "eonix_mm",
  "fdt",
- "riscv",
+ "riscv 0.13.0",
  "sbi",
  "spin",
 ]
@@ -107,9 +107,9 @@ dependencies = [
  "eonix_sync_base",
  "fdt",
  "intrusive_list",
- "riscv",
+ "riscv 0.13.0",
+ "riscv-peripheral",
  "sbi",
- "spin",
 ]
 
 [[package]]
@@ -347,6 +347,19 @@ dependencies = [
  "riscv-pac",
 ]
 
+[[package]]
+name = "riscv"
+version = "0.14.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0f1671c79a01a149fe000af2429ce9ccc8e58cdecda72672355d50e5536b363c"
+dependencies = [
+ "critical-section",
+ "embedded-hal",
+ "paste",
+ "riscv-macros",
+ "riscv-pac",
+]
+
 [[package]]
 name = "riscv-macros"
 version = "0.2.0"
@@ -364,6 +377,18 @@ version = "0.2.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "8188909339ccc0c68cfb5a04648313f09621e8b87dc03095454f1a11f6c5d436"
 
+[[package]]
+name = "riscv-peripheral"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d50c11ddf3e2a21206642bfe6d5e06f76d5225c1fbece09952dcd40f8c49409a"
+dependencies = [
+ "embedded-hal",
+ "paste",
+ "riscv 0.14.0",
+ "riscv-pac",
+]
+
 [[package]]
 name = "sbi"
 version = "0.3.0"

+ 3 - 0
Cargo.toml

@@ -56,6 +56,9 @@ opt-level = 2
 [profile.dev.package.intrusive_list]
 opt-level = 2
 
+[profile.dev.package.eonix_hal]
+opt-level = 0
+
 [profile.dev.package."*"]
 opt-level = "s"
 

+ 38 - 2
arch/arch_macros/src/riscv64/percpu.rs

@@ -7,13 +7,49 @@ pub fn get_percpu_pointer(percpu: &Ident, ty: &Type) -> TokenStream {
     quote! {
         {
             let base: *mut #ty;
+
+            unsafe extern "C" {
+                fn PERCPU_DATA_START();
+            }
+
             ::core::arch::asm!(
-                "la {base}, {offset}",
+                "la t0, {start}",
+                "la {base}, {var}",
+                "sub {base}, {base}, t0",
+                "add {base}, {base}, tp",
                 base = out(reg) base,
-                offset = sym #percpu,
+                start = sym PERCPU_DATA_START,
+                out("t0") _,
+                var = sym #percpu,
                 options(nostack, preserves_flags)
             );
+
             base
         }
     }
 }
+
+pub fn get_percpu_offset(percpu: &Ident) -> TokenStream {
+    quote! {
+        unsafe {
+            let offset: usize;
+
+            unsafe extern "C" {
+                fn PERCPU_DATA_START();
+            }
+
+            ::core::arch::asm!(
+                "la t0, {start}",
+                "la t1, {var}",
+                "sub t1, t1, t0",
+                start = sym PERCPU_DATA_START,
+                var = sym #percpu,
+                out("t0") _,
+                out("t1") offset,
+                options(nostack, preserves_flags)
+            );
+
+            offset
+        }
+    }
+}

+ 8 - 0
arch/arch_macros/src/x86_64/percpu.rs

@@ -30,3 +30,11 @@ pub fn get_percpu_pointer(percpu: &Ident, ty: &Type) -> TokenStream {
         }
     }
 }
+
+pub fn get_percpu_offset(percpu: &Ident) -> TokenStream {
+    quote! {
+        {
+            & #percpu as *const _ as usize
+        }
+    }
+}

+ 0 - 69
arch/src/riscv64/config.rs

@@ -1,69 +0,0 @@
-/// mm
-pub mod mm {
-    pub const ROOT_PAGE_TABLE_PHYS_ADDR: usize = 0x8040_0000;
-    pub const PHYS_MAP_VIRT: usize = 0xffff_ffc0_0000_0000;
-    pub const KIMAGE_PHYS_BASE: usize = 0x8020_0000;
-    pub const KIMAGE_OFFSET: usize = 0xffff_ffff_0000_0000;
-    pub const MMIO_VIRT_BASE: usize = KIMAGE_OFFSET;
-    pub const KIMAGE_VIRT_BASE: usize = KIMAGE_OFFSET + KIMAGE_PHYS_BASE;
-    pub const PAGE_SIZE: usize = 1 << PAGE_SIZE_BITS;
-    pub const PAGE_SIZE_BITS: usize = 12;
-    // 127GB
-    pub const MEMORY_SIZE: usize = 0x1F_C000_0000;
-
-    pub const PTE_SIZE: usize = 8;
-    pub const PTES_PER_PAGE: usize = PAGE_SIZE / PTE_SIZE;
-    pub const ROOT_PAGE_TABLE_PFN: usize = ROOT_PAGE_TABLE_PHYS_ADDR >> 12;
-    pub const PAGE_TABLE_PHYS_END: usize = 0x8080_0000;
-
-    #[derive(Clone, Copy)]
-    pub enum PageSize {
-        _4KbPage = 4096,
-        _2MbPage = 2 * 1024 * 1024,
-        _1GbPage = 1 * 1024 * 1024 * 1024,
-    }
-}
-
-/// smp
-pub mod smp {
-    use spin::Once;
-
-    pub static NUM_HARTS: Once<usize> = Once::new();
-
-    pub fn set_num_harts(num: usize) {
-        NUM_HARTS.call_once(|| num);
-    }
-
-    pub fn get_num_harts() -> usize {
-        *NUM_HARTS.get().expect("NUM_HARTS should be initialized by now")
-    }
-}
-
-pub mod platform {
-    pub mod virt {
-        pub const PLIC_BASE: usize = 0x0C00_0000;
-
-        pub const PLIC_ENABLE_PER_HART_OFFSET: usize = 0x80; // 每个 Hart使能块 0x80 字节 (128 字节)
-
-        pub const PLIC_THRESHOLD_CLAIM_COMPLETE_PER_HART_OFFSET: usize = 0x1000; // 每个 Hart/上下文块 0x1000 字节 (4KB)
-
-        pub const PLIC_PRIORITY_OFFSET: usize = 0x0000_0000;
-        pub const PLIC_PENDING_OFFSET: usize = 0x0000_1000;
-        pub const PLIC_ENABLE_OFFSET: usize = 0x0000_2000; // Varies by context and mode (M/S/U)
-        pub const PLIC_THRESHOLD_OFFSET: usize = 0x0020_0000; // Varies by context and mode (M/S/U)
-        pub const PLIC_CLAIM_COMPLETE_OFFSET: usize = 0x0020_0004; // Varies by context and mode (M/S/U)
-
-        // PLIC Context IDs for S-mode (assuming hart 0's S-mode context is 1, hart 1's is 3, etc.)
-        // A common pattern is: context_id = hart_id * 2 + 1 (for S-mode)
-        pub const PLIC_S_MODE_CONTEXT_STRIDE: usize = 2;
-
-        // CLINT (Core Local Interruptor) memory-mapped registers
-        // Base address for CLINT on QEMU virt platform
-        pub const CLINT_BASE: usize = 0x200_0000;
-        pub const CLINT_MSIP_OFFSET: usize = 0x0000;      // Machine-mode Software Interrupt Pending (MSIP)
-        pub const CLINT_MTIMECMP_OFFSET: usize = 0x4000;  // Machine-mode Timer Compare (MTIMECMP)
-        pub const CLINT_MTIME_OFFSET: usize = 0xBFF8;
-        pub const CPU_FREQ_HZ: u64 = 10_000_000;
-    }
-}
-

+ 0 - 16
arch/src/riscv64/console.rs

@@ -1,16 +0,0 @@
-use sbi::legacy::{console_putchar, console_getchar};
-
-pub fn getchar() -> Option<u8> {
-    let c = console_getchar();
-    if c == Some(!0) {
-        None
-    } else {
-        c
-    }
-}
-
-fn write_str(s: &str) {
-    for c in s.chars() {
-        console_putchar(c as u8);
-    }
-}

+ 0 - 178
arch/src/riscv64/context.rs

@@ -1,178 +0,0 @@
-use core::arch::naked_asm;
-
-#[repr(C)]
-#[derive(Debug, Default)]
-pub struct TaskContext {
-    // s0-11
-    s: [u64; 12],
-    sp: u64,
-    ra: u64,
-    sstatus: u64,
-}
-
-impl TaskContext {
-    pub const fn new() -> Self {
-        Self {
-            s: [0; 12],
-            sp: 0,
-            ra: 0,
-            sstatus: 0,
-        }
-    }
-
-    pub fn ip(&mut self, ip: usize) {
-        self.ra = ip as u64;
-    }
-
-    pub fn entry_point(&mut self, entry: usize) {
-        self.ra = entry as u64;
-    }
-
-    pub fn sp(&mut self, sp: usize) {
-        self.sp = sp as u64;
-    }
-
-    pub fn sstatus(&mut self, status: usize) {
-        self.sstatus = status as u64;
-    }
-
-    pub fn call1(&mut self, func: unsafe extern "C" fn(usize) -> !, arg: [usize; 1]) {
-        self.entry_point(Self::do_call as usize);
-        self.s[0] = func as u64;
-        self.s[1] = arg[0] as u64;
-    }
-
-    pub fn call2(&mut self, func: unsafe extern "C" fn(usize, usize) -> !, arg: [usize; 2]) {
-        self.entry_point(Self::do_call as usize);
-        self.s[0] = func as u64;
-        self.s[1] = arg[0] as u64;
-        self.s[2] = arg[1] as u64;
-    }
-
-    pub fn call3(&mut self, func: unsafe extern "C" fn(usize, usize, usize) -> !, arg: [usize; 3]) {
-        self.entry_point(Self::do_call as usize);
-        self.s[0] = func as u64;
-        self.s[1] = arg[0] as u64;
-        self.s[2] = arg[1] as u64;
-        self.s[3] = arg[2] as u64;
-    }
-
-    pub fn call4(
-        &mut self,
-        func: unsafe extern "C" fn(usize, usize, usize, usize) -> !,
-        arg: [usize; 4],
-    ) {
-        self.entry_point(Self::do_call as usize);
-        self.s[0] = func as u64;
-        self.s[1] = arg[0] as u64;
-        self.s[2] = arg[1] as u64;
-        self.s[3] = arg[2] as u64;
-        self.s[4] = arg[3] as u64;
-    }
-
-    pub fn call5(
-        &mut self,
-        func: unsafe extern "C" fn(usize, usize, usize, usize, usize) -> !,
-        arg: [usize; 5],
-    ) {
-        self.entry_point(Self::do_call as usize);
-        self.s[0] = func as u64;
-        self.s[1] = arg[0] as u64;
-        self.s[2] = arg[1] as u64;
-        self.s[3] = arg[2] as u64;
-        self.s[4] = arg[3] as u64;
-    }
-
-    pub fn interrupt(&mut self, is_enabled: bool) {
-        // sstatus: SIE bit is bit 1
-        const SSTATUS_SIE_BIT: u64 = 1 << 1; // 0x2
-
-        if is_enabled {
-            self.sstatus |= SSTATUS_SIE_BIT;
-        } else {
-            self.sstatus &= !SSTATUS_SIE_BIT;
-        }
-    }
-
-    /// SPIE bit
-    pub fn interrupt_on_return(&mut self, will_enable: bool) {
-        const SSTATUS_SPIE_BIT: u64 = 1 << 5;
-        if will_enable {
-            self.sstatus |= SSTATUS_SPIE_BIT;
-        } else {
-            self.sstatus &= !SSTATUS_SPIE_BIT;
-        }
-    }
-
-    #[naked]
-    #[no_mangle]
-    pub unsafe extern "C" fn __task_context_switch(from: *mut Self, to: *const Self) {
-        // Input arguments `from` and `to` will be in `a0` (x10) and `a1` (x11).
-        naked_asm!(
-            // Save current task's callee-saved registers to `from` context
-            "sd   s0, 0(a0)",
-            "sd   s1, 8(a0)",
-            "sd   s2, 16(a0)",
-            "sd   s3, 24(a0)",
-            "sd   s4, 32(a0)",
-            "sd   s5, 40(a0)",
-            "sd   s6, 48(a0)",
-            "sd   s7, 56(a0)",
-            "sd   s8, 64(a0)",
-            "sd   s9, 72(a0)",
-            "sd  s10, 80(a0)",
-            "sd  s11, 88(a0)",
-            "sd   sp, 96(a0)",
-            "sd   ra, 104(a0)",
-            "csrr s0, sstatus",
-            "sd   s0, 112(a0)", // Store sstatus at offset 112
-
-            // Load next task's callee-saved registers from `to` context
-            "ld   s0, 0(a1)",
-            "ld   s1, 8(a1)",
-            "ld   s2, 16(a1)",
-            "ld   s3, 24(a1)",
-            "ld   s4, 32(a1)",
-            "ld   s5, 40(a1)",
-            "ld   s6, 48(a1)",
-            "ld   s7, 56(a1)",
-            "ld   s8, 64(a1)",
-            "ld   s9, 72(a1)",
-            "ld  s10, 80(a1)",
-            "ld  s11, 88(a1)",
-            "ld   sp, 96(a1)",
-            "ld   ra, 104(a1)",
-            "ld   t0, 112(a1)",
-            "csrw sstatus, t0",
-
-            "ret",
-        );
-    }
-
-    pub fn switch(from: &mut Self, to: &mut Self) {
-        unsafe {
-            TaskContext::__task_context_switch(from, to);
-        }
-    }
-
-    #[naked]
-    #[no_mangle]
-    /// Maximum of 5 arguments supported.
-    unsafe extern "C" fn do_call() -> ! {
-        naked_asm!(
-            // Move function pointer.
-            "mv   t0, s0",
-
-            // Move arguments.
-            "mv   a0, s1",
-            "mv   a1, s2",
-            "mv   a2, s3",
-            "mv   a3, s4",
-            "mv   a4, s5",
-
-            "mv   s0, zero", // Set s0 (fp) to 0.
-
-            "jr   t0", // Jump to t0.
-        );
-    }
-}

+ 0 - 67
arch/src/riscv64/entry/mod.rs

@@ -1,67 +0,0 @@
-mod page;
-
-use page::setup_kernel_page_table;
-
-use super::{
-    config::{self, mm::*},
-    fdt::get_num_harts,
-};
-
-use core::arch::naked_asm;
-
-#[link_section = ".bss.stack"]
-static mut BOOT_STACK: [u8; 4096 * 16] = [0; 4096 * 16];
-
-#[repr(C, align(4096))]
-struct BootPageTable([u64; PTES_PER_PAGE]);
-
-/// map 0x8000 0000 to itself and 0xffff ffff 8000 0000
-static mut BOOT_PAGE_TABLE: BootPageTable = {
-    let mut arr: [u64; PTES_PER_PAGE] = [0; PTES_PER_PAGE];
-    arr[2] = (0x80000 << 10) | 0xcf;
-    arr[510] = (0x80000 << 10) | 0xcf;
-    BootPageTable(arr)
-};
-
-extern "C" {
-    fn kernel_init();
-}
-
-/// bootstrap in rust
-#[naked]
-#[no_mangle]
-#[link_section = ".text.entry"]
-unsafe extern "C" fn _start(hart_id: usize, dtb_addr: usize) -> ! {
-    naked_asm!(
-        "
-            la    sp, {boot_stack}
-            la    t0, {page_table}
-            srli  t0, t0, 12
-            li    t1, 8 << 60
-            or    t0, t0, t1
-            csrw  satp, t0
-            sfence.vma
-            li   t2, {virt_ram_offset}
-            or   sp, sp, t2
-            la   t3, riscv64_start
-            or   t3, t3, t2
-            jalr t3                      // call riscv64_start
-        ",
-        boot_stack = sym BOOT_STACK,
-        page_table = sym BOOT_PAGE_TABLE,
-        virt_ram_offset = const KIMAGE_OFFSET,
-    )
-}
-
-/// TODO: 
-/// linker,现在VMA和LMA不对
-/// kernel_init不知道要干什么
-#[no_mangle]
-pub unsafe extern "C" fn riscv64_start(hart_id: usize, dtb_addr: usize) -> ! {
-    setup_kernel_page_table();
-    let num_harts = get_num_harts(dtb_addr);
-    config::smp::set_num_harts(num_harts);
-    unsafe { kernel_init() };
-
-    unreachable!();
-}

+ 0 - 238
arch/src/riscv64/entry/page.rs

@@ -1,238 +0,0 @@
-use super::super::{
-    config::mm::*,
-    mm::*,
-};
-
-use core::{
-    ptr::NonNull,
-    sync::atomic::AtomicUsize
-};
-use intrusive_list::{container_of, Link};
-use buddy_allocator::{BuddyAllocator, BuddyRawPage};
-use riscv::{asm::sfence_vma_all, register::satp};
-use eonix_mm::{
-    address::{Addr as _, AddrOps, PAddr, VAddr, VRange},
-    page_table::{PageAttribute, PagingMode, RawAttribute, PTE as _},
-    paging::{Page, PageAccess, PageAlloc, PageBlock, RawPage as RawPageTrait, PFN},
-};
-use spin::Mutex;
-
-static mut PAGES: [RawPage; 1024] = [const { RawPage::new() }; 1024];
-
-fn page(index: usize) -> &'static mut RawPage {
-    let page = unsafe { PAGES.as_mut_ptr().add(index) };
-    unsafe { &mut *page }
-}
-
-#[derive(Clone, Copy)]
-struct RawPageHandle(usize);
-
-impl From<PFN> for RawPageHandle {
-    fn from(pfn: PFN) -> Self {
-        assert!(usize::from(pfn) - ROOT_PAGE_TABLE_PFN < 1024, "PFN out of range");
-
-        Self(usize::from(pfn) - ROOT_PAGE_TABLE_PFN)
-    }
-}
-
-impl From<RawPageHandle> for PFN {
-    fn from(raw_page: RawPageHandle) -> Self {
-        PFN::from(raw_page.0 + ROOT_PAGE_TABLE_PFN)
-    }
-}
-
-impl RawPageTrait for RawPageHandle {
-    fn order(&self) -> u32 {
-        page(self.0).order
-    }
-
-    fn refcount(&self) -> &AtomicUsize {
-        &page(self.0).refcount
-    }
-
-    fn is_present(&self) -> bool {
-        self.0 < 1024
-    }
-}
-
-impl BuddyRawPage for RawPageHandle {
-    unsafe fn from_link(link: &mut Link) -> Self {
-        let page = container_of!(link, RawPage, link);
-        let page_index = page.as_ptr().offset_from_unsigned(PAGES.as_ptr());
-        assert!(page_index < 1024, "Page index out of range");
-
-        Self(page_index)
-    }
-
-    unsafe fn get_link(&self) -> &mut Link {
-        &mut page(self.0).link
-    }
-
-    fn set_order(&self, order: u32) {
-        page(self.0).order = order;
-    }
-
-    fn is_buddy(&self) -> bool {
-        page(self.0).buddy
-    }
-
-    fn is_free(&self) -> bool {
-        page(self.0).free
-    }
-
-    fn set_buddy(&self) {
-        page(self.0).buddy = true;
-    }
-
-    fn set_free(&self) {
-        page(self.0).free = true;
-    }
-
-    fn clear_buddy(&self) {
-        page(self.0).buddy = false;
-    }
-
-    fn clear_free(&self) {
-        page(self.0).free = false;
-    }
-}
-
-struct RawPage {
-    link: Link,
-    free: bool,
-    buddy: bool,
-    order: u32,
-    refcount: AtomicUsize,
-}
-
-impl RawPage {
-    const fn new() -> Self {
-        Self {
-            link: Link::new(),
-            free: false,
-            buddy: false,
-            order: 0,
-            refcount: AtomicUsize::new(0),
-        }
-    }
-}
-
-struct DirectPageAccess;
-
-impl PageAccess for DirectPageAccess {
-    unsafe fn get_ptr_for_pfn(pfn: PFN) -> NonNull<PageBlock> {
-        unsafe { NonNull::new_unchecked(PAddr::from(pfn).addr() as *mut _) }
-    }
-}
-
-static BUDDY: Mutex<BuddyAllocator<RawPageHandle>> = Mutex::new(BuddyAllocator::new());
-
-#[derive(Clone)]
-struct BuddyPageAlloc;
-
-impl PageAlloc for BuddyPageAlloc {
-    type RawPage = RawPageHandle;
-
-    fn alloc_order(&self, order: u32) -> Option<Self::RawPage> {
-        let retval = BUDDY.lock().alloc_order(order);
-        retval
-    }
-
-    unsafe fn dealloc(&self, raw_page: Self::RawPage) {
-        BUDDY.lock().dealloc(raw_page);
-    }
-
-    fn has_management_over(&self, page_ptr: Self::RawPage) -> bool {
-        BuddyAllocator::has_management_over(page_ptr)
-    }
-}
-
-type PageTable<'a> = eonix_mm::page_table::PageTable<'a, PagingModeSv39, BuddyPageAlloc, DirectPageAccess>;
-
-extern "C" {
-    fn _ekernel();
-}
-
-/// TODO:
-/// _ekernel现在还没有,需要在linker里加上
-/// 对kernel image添加更细的控制,或者不加也行
-fn map_area(page_table: &PageTable, attr: PageAttribute, range: VRange, phy_offest: usize, page_size: PageSize) {
-    let (pfn_size, levels) = match page_size {
-        PageSize::_4KbPage => (0x1, &PagingModeSv39::LEVELS[..=0]),
-        PageSize::_2MbPage => (0x200, &PagingModeSv39::LEVELS[..=1]),
-        PageSize::_1GbPage => (0x40000, &PagingModeSv39::LEVELS[..=2]),
-    };
-    for (idx, pte) in page_table
-        .iter_kernel_levels(range, levels)
-        .enumerate()
-    {
-        pte.set(PFN::from(idx * pfn_size + phy_offest), PageAttribute64::from_page_attr(attr));
-    }
-}
-
-/// Map physical memory after ekernel, about 0x8040 0000-0x20_7fff_fff about 128GB
-/// to add a 0xffff ffc0 0000 0000 offest
-/// first use 4KB page, then 2MB page, last 1GB page
-fn map_free_physical_memory(attr: PageAttribute, page_table: &PageTable) {
-    let ekernel = _ekernel as usize - KIMAGE_OFFSET;
-
-    let start = PAddr::from(ekernel).ceil_to(PageSize::_4KbPage as usize);
-    let end = PAddr::from(ekernel).ceil_to(PageSize::_2MbPage as usize);
-    let size_4kb = end - start;
-    let range = VRange::from(VAddr::from(PHYS_MAP_VIRT + start.addr())).grow(size_4kb);
-    let pfn_start = start.addr() >> PAGE_SIZE_BITS;
-    map_area(page_table, attr, range, pfn_start, PageSize::_4KbPage);
-
-    let start = end;
-    let end = start.ceil_to(PageSize::_1GbPage as usize);
-    let size_2mb = end - start;
-    let range = VRange::from(VAddr::from(PHYS_MAP_VIRT + start.addr())).grow(size_2mb);
-    let pfn_start = start.addr() >> PAGE_SIZE_BITS;
-    map_area(page_table, attr, range, pfn_start, PageSize::_2MbPage);
-
-    let start = end;
-    let size_1gb = MEMORY_SIZE;
-    let range = VRange::from(VAddr::from(PHYS_MAP_VIRT + start.addr())).grow(size_1gb);
-    let pfn_start = start.addr() >> PAGE_SIZE_BITS;
-    map_area(page_table, attr, range, pfn_start, PageSize::_1GbPage);
-}
-
-pub fn setup_kernel_page_table() {
-    let attr = PageAttribute::WRITE
-        | PageAttribute::READ
-        | PageAttribute::EXECUTE
-        | PageAttribute::GLOBAL
-        | PageAttribute::PRESENT;
-
-    BUDDY.lock().create_pages(PAddr::from(ROOT_PAGE_TABLE_PHYS_ADDR), PAddr::from(PAGE_TABLE_PHYS_END));
-
-    let root_table_page = Page::alloc_in(BuddyPageAlloc);
-    let page_table = PageTable::new_in(&root_table_page, BuddyPageAlloc);
-
-    // Map 0x00000000-0x7fffffff 2GB MMIO,
-    // to 0xffff ffff 0000 0000 to 0xffff ffff 7ffff ffff, use 1GB page
-    map_area(&page_table,
-        attr,
-        VRange::from(VAddr::from(MMIO_VIRT_BASE)).grow(0x2000_0000),
-        0,
-        PageSize::_1GbPage);
-    
-    map_free_physical_memory(attr, &page_table);
-
-    // Map 2 MB kernel image
-    for (idx, pte) in page_table
-        .iter_kernel(VRange::from(VAddr::from(KIMAGE_VIRT_BASE)).grow(0x20_0000))
-        .enumerate()
-    {
-        pte.set(PFN::from(idx + 0x80200), PageAttribute64::from_page_attr(attr));
-    }
-
-    unsafe {
-        satp::set(
-            satp::Mode::Sv39,
-            0,
-            usize::from(PFN::from(page_table.addr())),
-        );
-    }
-    sfence_vma_all();
-}

+ 0 - 99
arch/src/riscv64/fdt.rs

@@ -1,99 +0,0 @@
-extern crate alloc;
-
-use alloc::{string::String, vec::Vec};
-
-#[derive(Debug, Clone)]
-pub struct HartInfo {
-    pub hart_id: usize,
-    pub compatible: Option<String>,
-}
-
-#[derive(Debug)]
-pub struct CpuManager {
-    pub num_harts: usize,
-    pub harts: Vec<HartInfo>,
-    pub boot_hart_id: usize,
-}
-
-impl CpuManager {
-    pub fn from_fdt(dtb_addr: usize, boot_hart_id: usize) -> Self {
-        let fdt = unsafe {
-            fdt::Fdt::from_ptr(dtb_addr as *const u8)
-                .expect("Failed to parse device tree from dtb_addr")
-        };
-
-        let mut harts_info = Vec::new();
-        let mut num_harts = 0;
-
-        if let Some(cpus_node) = fdt.find_node("/cpus") {
-            for cpu_node in cpus_node.children() {
-                let mut is_riscv_cpu = false;
-                let compatible_string: Option<String> = 
-                    if let Some(compatible_prop) = cpu_node
-                        .properties()
-                        .find(|p| p.name == "compatible")
-                    {
-                        if let Some(s) = compatible_prop.as_str() {
-                            if s.starts_with("riscv,") {
-                                is_riscv_cpu = true;
-                            }
-                            Some(String::from(s))
-                        } else {
-                            None
-                        }
-                    } else {
-                        None
-                    };
-
-                if is_riscv_cpu {
-                    let hart_id = if let Some(hart_id_prop) = cpu_node
-                        .properties()
-                        .find(|p| p.name == "hartid")
-                    {
-                        hart_id_prop.as_usize()
-                            .expect("hartid property in CPU node is not a valid integer")
-                    } else if let Some(reg_prop) = cpu_node
-                        .properties()
-                        .find(|p| p.name == "reg")
-                    {
-                        reg_prop.as_usize()
-                            .expect("reg property in CPU node is not a valid integer for hartid")
-                    } else {
-                        panic!("CPU node {:?} does not have a 'hartid' or 'reg' property required for its ID", cpu_node.name);
-                    };
-
-                    let hart_info = HartInfo {
-                        hart_id,
-                        compatible: compatible_string,
-                    };
-                    harts_info.push(hart_info);
-                    num_harts += 1;
-                }
-            }
-        } else {
-            panic!("Device Tree does not contain a /cpus node!");
-        }
-
-        harts_info.sort_by_key(|h| h.hart_id);
-
-        Self {
-            num_harts,
-            harts: harts_info,
-            boot_hart_id,
-        }
-    }
-}
-
-pub fn get_num_harts(dtb_addr: usize) -> usize {
-    let fdt = unsafe {
-        fdt::Fdt::from_ptr(dtb_addr as *const u8)
-            .expect("Failed to parse device tree from dtb_addr")
-    };
-    let dtb_cpus = fdt.cpus();
-    let mut num_harts = 0;
-
-    for _cpu in dtb_cpus {
-        num_harts += 1;
-    }
-    num_harts
-}

+ 0 - 145
arch/src/riscv64/init.rs

@@ -1,145 +0,0 @@
-use core::pin::Pin;
-use riscv::register::{
-    mhartid,
-    sscratch,
-    sstatus
-};
-use sbi::PhysicalAddress;
-
-/// TODO:
-/// 中断handler
-/// 
-
-use super::{config::smp::get_num_harts, enable_sse, setup_kernel_satp, setup_kernel_trap, InterruptControl};
-
-/// RISC-V Hart
-pub struct CPU {
-    hart_id: usize,
-    interrupt: InterruptControl,
-}
-
-impl CPU {
-    pub fn new() -> Self {
-        let hart_id = read_hart_id();
-        Self {
-            hart_id: hart_id,
-            interrupt: InterruptControl::new(hart_id),
-        }
-    }
-
-    /// Load CPU specific configurations for the current Hart.
-    ///
-    /// # Safety
-    /// This function performs low-level hardware initialization and should
-    /// only be called once per Hart during its boot sequence.
-    pub unsafe fn init(self: Pin<&mut Self>) {
-        enable_sse();
-        let self_mut = self.get_unchecked_mut();
-
-        sscratch::write(self_mut.hart_id as usize);
-
-        setup_kernel_trap();
-
-        // CLINT, 10_000 ms
-        self_mut.interrupt.setup_timer(10_000);
-
-        // Supervisor Mode Status Register (sstatus)
-        // SUM (Supervisor User Memory access): support S-mode access user memory
-        // MXR (Make Executable Readable)
-        // SIE (Supervisor Interrupt Enable): enable S-mode interrupt
-        let mut current_sstatus = sstatus::read();
-        current_sstatus.set_spp(sstatus::SPP::Supervisor);
-        current_sstatus.set_sum(true);
-        current_sstatus.set_mxr(true);
-        current_sstatus.set_sie(true);
-        sstatus::write(current_sstatus);
-
-        // setup kernel page table and flush tlb
-        setup_kernel_satp();
-    }
-
-    /// Boot all other hart.
-    pub unsafe fn bootstrap_cpus(&self) {
-        extern "C" {
-        fn ap_boot_entry();
-        }
-        let total_harts = get_num_harts();
-
-        let ap_entry_point = PhysicalAddress::new(ap_boot_entry as usize);
-
-        for i in 1..total_harts {
-            sbi::hsm::hart_start(i, ap_entry_point, 0)
-                .expect("Failed to start secondary hart via SBI");
-        }
-    }
-
-    pub fn cpuid(&self) -> usize {
-        self.hart_id
-    }
-}
-
-fn read_hart_id() -> usize {
-    mhartid::read()
-}
-
-#[macro_export]
-macro_rules! define_smp_bootstrap {
-    ($cpu_count:literal, $ap_entry:ident, $alloc_kstack:tt) => {
-        #[no_mangle]
-        static BOOT_SEMAPHORE: core::sync::atomic::AtomicU64 =
-            core::sync::atomic::AtomicU64::new(0);
-        #[no_mangle]
-        static BOOT_STACK: core::sync::atomic::AtomicU64 =
-            core::sync::atomic::AtomicU64::new(0);
-
-        #[no_mangle]
-        static CPU_COUNT: core::sync::atomic::AtomicU64 =
-            core::sync::atomic::AtomicU64::new(0);
-
-        core::arch::global_asm!(
-            r#"
-        .section .text.ap_boot
-        .globl ap_boot_entry
-
-        ap_boot_entry:
-            csrr a0, mhartid
-
-        1:
-            lw t0, AP_BOOT_STACK.addr
-            beqz t0, 1b
-            li t1, 0
-            sw t1, AP_BOOT_STACK.addr
-            mv sp, t0
-
-        2:
-            lw t0, AP_BOOT_SEMAPHORE.addr
-            beqz t0, 2b
-
-            li t1, 0
-            sw t1, AP_BOOT_SEMAPHORE.addr
-
-            li t0, 1
-            amoswap.w.aq rl t0, a0, ONLINE_HART_COUNT.addr
-
-            call $ap_entry
-            j .
-            "#,
-            BOOT_SEMAPHORE = sym BOOT_SEMAPHORE,
-            BOOT_STACK = sym BOOT_STACK,
-            CPU_COUNT = sym CPU_COUNT,
-            AP_ENTRY = sym $ap_entry,
-        );
-
-        pub unsafe fn wait_cpus_online() {
-            use core::sync::atomic::Ordering;
-            while CPU_COUNT.load(Ordering::Acquire) != $cpu_count - 1 {
-                if BOOT_STACK.load(Ordering::Acquire) == 0 {
-                    let stack_bottom = $alloc_kstack as u64;
-                    BOOT_STACK.store(stack_bottom, Ordering::Release);
-                }
-                $crate::pause();
-            }
-        }
-    };
-}
-

+ 0 - 62
arch/src/riscv64/interrupt/clint.rs

@@ -1,62 +0,0 @@
-use super::super::config::platform::virt::*;
-use core::ptr;
-
-use sbi::{
-    ipi::send_ipi,
-    timer::set_timer,
-    HartMask,
-    SbiError
-};
-use riscv::register::mie;
-
-/// CLINT (Core Local Interruptor) driver
-/// This struct now owns the base address and hart_id.
-pub struct ClintDriver {
-    base_addr: usize,
-    hart_id: usize,
-}
-
-impl ClintDriver {
-    pub fn new(base_addr: usize, hart_id: usize) -> Self {
-        let driver = ClintDriver { base_addr, hart_id };
-
-        driver.clear_soft_interrupt_pending(hart_id);
-
-        // Enable Supervisor-mode Software Interrupts (SSIE)
-        // and Supervisor-mode Timer Interrupts (STIE) in the `mie` CSR.
-        unsafe {
-            mie::set_ssoft(); // Enable S-mode Software Interrupts
-            mie::set_stimer(); // Enable S-mode Timer Interrupts
-        }
-
-        driver
-    }
-
-    /// Reads the current value of the global MTIME (Machine Timer) counter.
-    pub fn get_time(&self) -> u64 {
-        unsafe {
-            // MTIME is a 64-bit counter at CLINT_BASE + CLINT_MTIME_OFFSET
-            ptr::read_volatile((self.base_addr + CLINT_MTIME_OFFSET) as *mut u64)
-        }
-    }
-
-    /// Sets the next timer interrupt trigger point using SBI.
-    pub fn set_timer(&self, time_value: u64) -> Result<(), SbiError> {
-        set_timer(time_value)
-    }
-
-    /// Sends an Inter-Processor Interrupt (IPI) to the specified Hart(s).
-    pub fn send_ipi(&self, hart_id_mask: usize) -> Result<(), SbiError> {
-        // This utilizes the SBI `send_ipi` call.
-        send_ipi(HartMask::from(hart_id_mask))
-    }
-
-    /// Clears the software interrupt pending bit for the specified Hart.
-    pub fn clear_soft_interrupt_pending(&self, hart_id: usize) {
-        unsafe {
-            // MSIP registers are typically located at CLINT_BASE + 4 * hart_id.
-            // Writing 0 to the register clears the pending bit.
-            ptr::write_volatile((self.base_addr + CLINT_MSIP_OFFSET + hart_id * 4) as *mut u32, 0);
-        }
-    }
-}

+ 0 - 319
arch/src/riscv64/interrupt/context.rs

@@ -1,319 +0,0 @@
-use core::arch::asm;
-use riscv::{
-    interrupt::{Exception, Interrupt, Trap}, register::{
-        scause, sie, sstatus::{self, Sstatus, SPP}, stval
-    }, ExceptionNumber, InterruptNumber
-};
-
-/// Floating-point registers context.
-#[repr(C)]
-#[derive(Debug, Clone, Copy, Default)]
-pub struct FpuRegisters {
-    pub f: [u64; 32],
-    pub fcsr: u32,
-}
-
-/// Saved CPU context when a trap (interrupt or exception) occurs on RISC-V 64.
-#[repr(C)]
-#[derive(Debug, Clone, Copy)]
-pub struct TrapContext {
-    pub x: [usize; 32],
-
-    // CSRs
-    pub sstatus: Sstatus, // sstatus CSR value. Contains privilege mode, interrupt enable, FPU state.
-    pub sepc: usize,    // sepc (Supervisor Exception Program Counter). Program counter at trap.
-    
-    pub kernel_sp: usize,
-    pub kernel_ra: usize,
-    pub kernel_s: [usize; 12],
-    pub kernel_fp: usize,
-    pub kernel_tp: usize,
-
-    // may need to save
-    // FPU
-    // pub fpu_regs: FpuRegisters,
-}
-
-impl FpuRegisters {
-    pub fn new() -> Self {
-        unsafe { core::mem::zeroed() }
-    }
-
-    /// Save reg -> mem
-    pub fn save(&mut self) {
-        unsafe {
-            let base_ptr: *mut u64 = self.f.as_mut_ptr();
-            let fcsr_ptr: *mut u32 = &mut self.fcsr;
-            let mut _fcsr_val: u32 = 0;
-            asm!(
-            "fsd f0,  (0 * 8)({base})",
-            "fsd f1,  (1 * 8)({base})",
-            "fsd f2,  (2 * 8)({base})",
-            "fsd f3,  (3 * 8)({base})",
-            "fsd f4,  (4 * 8)({base})",
-            "fsd f5,  (5 * 8)({base})",
-            "fsd f6,  (6 * 8)({base})",
-            "fsd f7,  (7 * 8)({base})",
-            "fsd f8,  (8 * 8)({base})",
-            "fsd f9,  (9 * 8)({base})",
-            "fsd f10, (10 * 8)({base})",
-            "fsd f11, (11 * 8)({base})",
-            "fsd f12, (12 * 8)({base})",
-            "fsd f13, (13 * 8)({base})",
-            "fsd f14, (14 * 8)({base})",
-            "fsd f15, (15 * 8)({base})",
-            "fsd f16, (16 * 8)({base})",
-            "fsd f17, (17 * 8)({base})",
-            "fsd f18, (18 * 8)({base})",
-            "fsd f19, (19 * 8)({base})",
-            "fsd f20, (20 * 8)({base})",
-            "fsd f21, (21 * 8)({base})",
-            "fsd f22, (22 * 8)({base})",
-            "fsd f23, (23 * 8)({base})",
-            "fsd f24, (24 * 8)({base})",
-            "fsd f25, (25 * 8)({base})",
-            "fsd f26, (26 * 8)({base})",
-            "fsd f27, (27 * 8)({base})",
-            "fsd f28, (28 * 8)({base})",
-            "fsd f29, (29 * 8)({base})",
-            "fsd f30, (30 * 8)({base})",
-            "fsd f31, (31 * 8)({base})",
-            "csrr {fcsr_val}, fcsr", // Read fcsr into fcsr_val (which is in a general-purpose register)
-            "sw {fcsr_val}, 0({fcsr_ptr})",
-            base = in(reg) base_ptr,
-            fcsr_val = out(reg) _fcsr_val,
-            fcsr_ptr = in(reg) fcsr_ptr,
-            options(nostack, nomem, preserves_flags));
-        }
-    }
-
-    pub fn restore(&mut self) {
-        let base_ptr: *const u64 = self.f.as_ptr();
-        let fcsr_ptr: *const u32 = &self.fcsr;
-        let mut _fcsr_val: u64;
-
-        unsafe {
-            asm!(
-            "fld f0,  (0 * 8)({base})",
-            "fld f1,  (1 * 8)({base})",
-            "fld f2,  (2 * 8)({base})",
-            "fld f3,  (3 * 8)({base})",
-            "fld f4,  (4 * 8)({base})",
-            "fld f5,  (5 * 8)({base})",
-            "fld f6,  (6 * 8)({base})",
-            "fld f7,  (7 * 8)({base})",
-            "fld f8,  (8 * 8)({base})",
-            "fld f9,  (9 * 8)({base})",
-            "fld f10, (10 * 8)({base})",
-            "fld f11, (11 * 8)({base})",
-            "fld f12, (12 * 8)({base})",
-            "fld f13, (13 * 8)({base})",
-            "fld f14, (14 * 8)({base})",
-            "fld f15, (15 * 8)({base})",
-            "fld f16, (16 * 8)({base})",
-            "fld f17, (17 * 8)({base})",
-            "fld f18, (18 * 8)({base})",
-            "fld f19, (19 * 8)({base})",
-            "fld f20, (20 * 8)({base})",
-            "fld f21, (21 * 8)({base})",
-            "fld f22, (22 * 8)({base})",
-            "fld f23, (23 * 8)({base})",
-            "fld f24, (24 * 8)({base})",
-            "fld f25, (25 * 8)({base})",
-            "fld f26, (26 * 8)({base})",
-            "fld f27, (27 * 8)({base})",
-            "fld f28, (28 * 8)({base})",
-            "fld f29, (29 * 8)({base})",
-            "fld f30, (30 * 8)({base})",
-            "fld f31, (31 * 8)({base})",
-            "lw {fcsr_val}, 0({fcsr_ptr})", // Load from memory (fcsr_ptr)
-            "csrw fcsr, {fcsr_val}",
-            base = in(reg) base_ptr,
-            fcsr_val = out(reg) _fcsr_val,
-            fcsr_ptr = in(reg) fcsr_ptr,
-            options(nostack, nomem, preserves_flags));
-        }
-    }
-}
-
-
-/// TODO: will be displaced after origin's branch be mergered.
-use bitflags::bitflags;
-bitflags! {
-    #[derive(Debug)]
-    pub struct PageFaultErrorCode: u32 {
-        const NonPresent = 1;
-        const Read = 2;
-        const Write = 4;
-        const InstructionFetch = 8;
-        const UserAccess = 16;
-    }
-}
-
-#[derive(Debug)]
-pub enum Fault {
-    InvalidOp,
-    BadAccess,
-    PageFault(PageFaultErrorCode),
-    Unknown(usize),
-}
-
-pub enum TrapType {
-    Syscall { no: usize, args: [usize; 6] },
-    Fault(Fault),
-    Irq(usize),
-    Timer,
-}
-
-impl TrapContext {
-    /// TODO: temporarily all zero, may change in future
-    pub fn new() -> Self {
-        Self {
-            x: [0; 32],
-            sstatus: sstatus::read(),
-            sepc: 0,
-            kernel_sp: 0,
-            kernel_ra: 0,
-            kernel_s: [0; 12],
-            kernel_fp: 0,
-            kernel_tp: 0
-        }
-    }
-
-    fn syscall_no(&self) -> usize {
-        self.x[17]
-    }
-
-    fn syscall_args(&self) -> [usize; 6] {
-        [
-            self.x[10],
-            self.x[11],
-            self.x[12],
-            self.x[13],
-            self.x[14],
-            self.x[15],
-        ]
-    }
-
-    pub fn trap_type(&self) -> TrapType {
-        let scause = scause::read();
-        let cause = scause.cause();
-        match cause {
-            Trap::Interrupt(i) => {
-                match Interrupt::from_number(i).unwrap() {
-                    Interrupt::SupervisorTimer => TrapType::Timer,
-                    Interrupt::SupervisorExternal => TrapType::Irq(0),
-                    // soft interrupt
-                    _ => TrapType::Fault(Fault::Unknown(i)),
-                }
-            }
-            Trap::Exception(e) => {
-                match Exception::from_number(e).unwrap() {
-                    Exception::InstructionMisaligned |
-                    Exception::LoadMisaligned |
-                    Exception::InstructionFault |
-                    Exception::LoadFault |
-                    Exception::StoreFault |
-                    Exception::StoreMisaligned => {
-                        TrapType::Fault(Fault::BadAccess)
-                    },
-                    Exception::IllegalInstruction => {
-                        TrapType::Fault(Fault::InvalidOp)
-                    }
-                    Exception::UserEnvCall => {
-                        TrapType::Syscall { 
-                            no: self.syscall_no(),
-                            args: self.syscall_args()
-                        }
-                    },
-                    Exception::InstructionPageFault |
-                    Exception::LoadPageFault |
-                    Exception::StorePageFault => {
-                        let e = Exception::from_number(e).unwrap();
-                        TrapType::Fault(Fault::PageFault(get_page_fault_error_code(e)))
-                    },
-                    // breakpoint and supervisor env call
-                    _ => TrapType::Fault(Fault::Unknown(e)),
-                }
-            },
-        }
-    }
-
-    pub fn get_program_counter(&self) -> usize {
-        self.sepc
-    }
-
-    pub fn get_stack_pointer(&self) -> usize {
-        self.x[2]
-    }
-
-    pub fn set_program_counter(&mut self, pc: usize) {
-        self.sepc = pc;
-    }
-
-    pub fn set_stack_pointer(&mut self, sp: usize) {
-        self.x[2] = sp;
-    }
-
-    pub fn is_interrupt_enabled(&self) -> bool {
-        self.sstatus.sie()
-    }
-
-    /// TODO: may need more precise control
-    pub fn set_interrupt_enabled(&mut self, enabled: bool) {
-        if enabled {
-            self.sstatus.set_sie(enabled);
-            unsafe { 
-                sie::set_sext();
-                sie::set_ssoft();
-                sie::set_stimer();
-            };
-        } else {
-            self.sstatus.set_sie(enabled);
-            unsafe { 
-                sie::clear_sext();
-                sie::clear_ssoft();
-                sie::clear_stimer();
-            };
-        }
-    }
-
-    pub fn is_user_mode(&self) -> bool {
-        self.sstatus.spp() == SPP::User
-    }
-
-    pub fn set_user_mode(&mut self, user: bool) {
-        match user {
-            true => self.sstatus.set_spp(SPP::User),
-            false => self.sstatus.set_spp(SPP::Supervisor),
-        }
-    }
-
-    pub fn set_user_return_value(&mut self, retval: usize) {
-        self.sepc = retval;
-    }
-}
-
-/// TODO: get PageFaultErrorCode also need check pagetable
-fn get_page_fault_error_code(exception_type: Exception) -> PageFaultErrorCode {
-    let scause_val = stval::read();
-    let mut error_code = PageFaultErrorCode::empty();
-
-    match exception_type {
-        Exception::InstructionPageFault => {
-            error_code |= PageFaultErrorCode::InstructionFetch;
-            error_code |= PageFaultErrorCode::Read;
-        }
-        Exception::LoadPageFault => {
-            error_code |= PageFaultErrorCode::Read;
-        }
-        Exception::StorePageFault => {
-            error_code |= PageFaultErrorCode::Write;
-        }
-        _ => {
-            unreachable!();
-        }
-    }
-    // TODO: here need check pagetable to confirm NonPresent and UserAccess
-    error_code
-}

+ 0 - 161
arch/src/riscv64/interrupt/mod.rs

@@ -1,161 +0,0 @@
-mod plic;
-mod clint;
-mod context;
-mod trap;
-
-use plic::*;
-use clint::*;
-use context::*;
-use trap::*;
-
-/// TODO:
-/// 切换回到user的入口函数
-/// percpu
-/// user?
-
-use riscv::{
-    asm::sfence_vma_all,
-    register::{
-        sstatus::{self, Sstatus},
-        stvec::{self, Stvec}
-    }
-};
-use sbi::SbiError;
-use core::arch::global_asm;
-
-use super::platform::virt::*;
-
-global_asm!(include_str!("trap.S"));
-
-#[derive(Debug, Clone, Copy, PartialEq, Eq)]
-pub struct IrqState(usize);
-
-impl IrqState {
-    #[inline]
-    pub fn save() -> Self {
-        let sstatus_val = sstatus::read().bits();
-
-        unsafe {
-            sstatus::clear_sie();
-        }
-
-        IrqState(sstatus_val)
-    }
-
-    #[inline]
-    pub fn restore(self) {
-        let Self(state) = self;
-        unsafe {
-            sstatus::write(Sstatus::from_bits(state));
-        }
-    }
-
-    #[inline]
-    pub fn was_enabled(&self) -> bool {
-        (self.0 & (1 << 1)) != 0
-    }
-}
-
-#[inline]
-pub fn disable_interrupts() {
-    unsafe {
-        sstatus::clear_sie();
-    }
-}
-
-#[inline]
-pub fn enable_interrupts() {
-    unsafe {
-        sstatus::set_sie();
-    }
-}
-
-/// Architecture-specific interrupt control block.
-pub struct InterruptControl {
-    hart_id: usize,
-    plic: PlicDriver,
-    clint: ClintDriver,
-}
-
-impl InterruptControl {
-    /// # Safety
-    /// should be called only once.
-    pub(crate) fn new(hart_id: usize) -> Self {
-        // Initialize PLICDriver for this Hart
-        let plic = PlicDriver::new(PLIC_BASE, hart_id);
-
-        // Initialize ClintDriver for this Hart
-        let clint = ClintDriver::new(CLINT_BASE, hart_id);
-
-        Self {
-            hart_id,
-            plic: plic,
-            clint: clint,
-        }
-    }
-
-    /// Configures the CLINT timer for a periodic interrupt.
-    ///
-    /// # Arguments
-    /// * `interval_us`: The desired interval between timer interrupts in microseconds.
-    pub fn setup_timer(&self, interval_us: u64) {
-        let current_time = self.clint.get_time();
-        // Calculate ticks per microsecond based on CPU_FREQ_HZ
-        let ticks_per_us = CPU_FREQ_HZ / 1_000_000;
-        let ticks = interval_us * ticks_per_us;
-
-        let next_timer_at = current_time.checked_add(ticks).unwrap_or(u64::MAX);
-
-        if let Err(e) = self.clint.set_timer(next_timer_at) {
-            panic!("Failed to set CLINT timer: {:?}", e);
-        }
-    }
-
-    /// Sends an Inter-Processor Interrupt (IPI) to target Harts.
-    pub fn send_ipi(&self, target_hart_mask: usize) -> Result<(), SbiError> {
-        self.clint.send_ipi(target_hart_mask)
-    }
-
-    /// Handles the "End Of Interrupt" (EOI) for the most recently claimed
-    /// external interrupt.
-    pub fn end_of_external_interrupt(&self, irq_id: u32) {
-        self.plic.complete_interrupt(irq_id);
-    }
-
-    /// Clears the pending software interrupt for the current Hart.
-    pub fn clear_soft_interrupt_pending(&self) {
-        self.clint.clear_soft_interrupt_pending(self.hart_id);
-    }
-
-    pub fn plic_enable_interrupt(&self, irq_id: u32) {
-        self.plic.enable_interrupt(irq_id);
-    }
-
-    pub fn plic_set_priority(&self, irq_id: u32, priority: u32) {
-        self.plic.set_priority(irq_id, priority);
-    }
-
-    pub fn plic_claim_interrupt(&self) -> u32 {
-        self.plic.claim_interrupt()
-    }
-}
-
-extern "C" {
-    fn trap_from_kernel();
-    fn trap_from_user();
-}
-
-fn setup_trap_handler(trap_entry_addr: usize) {
-    unsafe {
-        stvec::write(Stvec::from_bits(trap_entry_addr));
-    }
-    sfence_vma_all();
-}
-
-pub fn setup_kernel_trap() {
-    setup_trap_handler(trap_from_kernel as usize);
-}
-
-pub fn setup_user_trap() {
-    setup_trap_handler(trap_from_user as usize);
-}

+ 0 - 137
arch/src/riscv64/interrupt/plic.rs

@@ -1,137 +0,0 @@
-use core::ptr::{read_volatile, write_volatile};
-
-use super::super::config::platform::virt::*;
-
-use riscv::register::mie;
-
-pub struct PlicDriver {
-    base_addr: usize,
-    hart_id: usize,
-}
-
-impl PlicDriver {
-    pub fn new(base_addr: usize, hart_id: usize) -> Self {
-        let driver = PlicDriver { base_addr, hart_id };
-
-        let s_context_id = driver.s_context_id();
-
-        driver.set_priority_threshold(0);
-
-        let enable_reg_base_for_context = driver.enable_addr(s_context_id);
-        // PLIC enable bits are grouped into 32-bit registers.
-        // Assuming 32 registers for up to 1024 IRQs, but 32 is common for a few hundred.
-        for i in 0..(driver.max_irq_num() / 32 + 1) {
-            let reg_addr = (enable_reg_base_for_context as usize + (i as usize) * 4) as *mut u32;
-            unsafe {
-                (reg_addr as *mut u32).write_volatile(0);
-            }
-        }
-
-        unsafe {
-            mie::set_sext();
-        }
-
-        driver.set_priority(10, 1);
-        driver.enable_interrupt(10);
-
-        // TODO: may need more set_priority
-        // driver.set_priority(UART_IRQ_ID, 1);
-        // driver.enable_interrupt(UART_IRQ_ID);
-        // driver.set_priority(VIRTIO_BLOCK_IRQ_ID, 1);
-        // driver.enable_interrupt(VIRTIO_BLOCK_IRQ_ID);
-
-        driver
-    }
-
-    fn s_context_id(&self) -> usize {
-        self.hart_id * PLIC_S_MODE_CONTEXT_STRIDE + 1
-    }
-
-    fn priority_addr(&self, irq_id: u32) -> *mut u32 {
-        (self.base_addr + PLIC_PRIORITY_OFFSET + (irq_id as usize) * 4) as *mut u32
-    }
-
-    fn pending_addr(&self) -> *mut u32 {
-        (self.base_addr + PLIC_PENDING_OFFSET) as *mut u32
-    }
-
-    fn enable_addr(&self, context_id: usize) -> *mut u32 {
-        // PLIC enable bits are typically organized as 32-bit banks.
-        // The offset for each context's enable registers.
-        // A common stride for context enable blocks is 0x80 (128 bytes).
-        (self.base_addr + PLIC_ENABLE_OFFSET + context_id * PLIC_ENABLE_PER_HART_OFFSET) as *mut u32
-    }
-
-    fn threshold_addr(&self, context_id: usize) -> *mut u32 {
-        // A common stride for context threshold/claim/complete registers is 0x1000 (4KB).
-        (self.base_addr + PLIC_THRESHOLD_OFFSET + context_id * PLIC_THRESHOLD_CLAIM_COMPLETE_PER_HART_OFFSET) as *mut u32
-    }
-
-    fn claim_complete_addr(&self, context_id: usize) -> *mut u32 {
-        (self.base_addr + PLIC_CLAIM_COMPLETE_OFFSET + context_id * PLIC_THRESHOLD_CLAIM_COMPLETE_PER_HART_OFFSET) as *mut u32
-    }
-
-    pub fn set_priority(&self, irq_id: u32, priority: u32) {
-        unsafe {
-            write_volatile(self.priority_addr(irq_id), priority);
-        }
-    }
-
-    pub fn get_priority(&self, irq_id: u32) -> u32 {
-        unsafe { read_volatile(self.priority_addr(irq_id)) }
-    }
-
-    pub fn enable_interrupt(&self, irq_id: u32) {
-        let context_id = self.s_context_id();
-        let enable_reg_offset_in_bank = (irq_id / 32) as usize * 4;
-        let bit_index_in_reg = irq_id % 32;
-
-        let enable_reg_addr = (self.enable_addr(context_id) as usize + enable_reg_offset_in_bank) as *mut u32;
-        let bit_mask = 1 << bit_index_in_reg;
-        unsafe {
-            let old = read_volatile(enable_reg_addr);
-            write_volatile(enable_reg_addr, old | bit_mask);
-        }
-    }
-
-    pub fn disable_interrupt(&self, irq_id: u32) {
-        let context_id = self.s_context_id();
-        let enable_reg_offset_in_bank = (irq_id / 32) as usize * 4;
-        let bit_index_in_reg = irq_id % 32;
-
-        let enable_reg_addr = (self.enable_addr(context_id) as usize + enable_reg_offset_in_bank) as *mut u32;
-        let bit_mask = 1 << bit_index_in_reg;
-        unsafe {
-            let old = read_volatile(enable_reg_addr);
-            write_volatile(enable_reg_addr, old & !bit_mask);
-        }
-    }
-
-    pub fn set_priority_threshold(&self, threshold: u32) {
-        let context_id = self.s_context_id();
-        unsafe {
-            write_volatile(self.threshold_addr(context_id), threshold);
-        }
-    }
-
-    pub fn get_priority_threshold(&self) -> u32 {
-        let context_id = self.s_context_id();
-        unsafe { read_volatile(self.threshold_addr(context_id)) }
-    }
-
-    pub fn claim_interrupt(&self) -> u32 {
-        let context_id = self.s_context_id();
-        unsafe { read_volatile(self.claim_complete_addr(context_id)) }
-    }
-
-    pub fn complete_interrupt(&self, irq_id: u32) {
-        let context_id = self.s_context_id();
-        unsafe {
-            write_volatile(self.claim_complete_addr(context_id), irq_id);
-        }
-    }
-
-    pub fn max_irq_num(&self) -> u32 {
-        127
-    }
-}

+ 0 - 139
arch/src/riscv64/interrupt/trap.S

@@ -1,139 +0,0 @@
-.altmacro
-.macro SAVE_GP n
-    sd x\n, \n*8(sp)
-.endm
-.macro LOAD_GP n
-    ld x\n, \n*8(sp)
-.endm
-
-.section .text
-    .globl trap_from_kernel
-    .globl trap_from_user
-    .globl return_to_user
-    .align 2
-
-# just like a function call
-trap_from_kernel:
-    # save s*
-    addi sp, sp, -17*8
-    sd  ra,  1*8(sp)
-    sd  t0,  2*8(sp)
-    sd  t1,  3*8(sp)
-    sd  t2,  4*8(sp)
-    sd  t3,  5*8(sp)
-    sd  t4,  6*8(sp)
-    sd  t5,  7*8(sp)
-    sd  t6,  8*8(sp)
-    sd  a0,  9*8(sp)
-    sd  a1, 10*8(sp)
-    sd  a2, 11*8(sp)
-    sd  a3, 12*8(sp)
-    sd  a4, 13*8(sp)
-    sd  a5, 14*8(sp)
-    sd  a6, 15*8(sp)
-    sd  a7, 16*8(sp)
-
-    call kernel_trap_entry
-
-    # restore s*
-    ld  ra,  1*8(sp)
-    ld  t0,  2*8(sp)
-    ld  t1,  3*8(sp)
-    ld  t2,  4*8(sp)
-    ld  t3,  5*8(sp)
-    ld  t4,  6*8(sp)
-    ld  t5,  7*8(sp)
-    ld  t6,  8*8(sp)
-    ld  a0,  9*8(sp)
-    ld  a1, 10*8(sp)
-    ld  a2, 11*8(sp)
-    ld  a3, 12*8(sp)
-    ld  a4, 13*8(sp)
-    ld  a5, 14*8(sp)
-    ld  a6, 15*8(sp)
-    ld  a7, 16*8(sp)
-    addi sp, sp, 17*8
-
-    sret
-
-trap_from_user:
-    # swap sp and sscratch(previously stored user TrapContext's address in return_to_user)
-    csrrw sp, sscratch, sp
-
-    sd x1, 1*8(sp)
-    .set n, 3
-    .rept 29
-        SAVE_GP %n
-        .set n, n+1
-    .endr
-
-    csrr t0, sstatus
-    csrr t1, sepc
-    sd t0, 32*8(sp)     # save sstatus into the TrapContext
-    sd t1, 33*8(sp)     # save sepc into the TrapContext
-
-    csrr t2, sscratch
-    sd t2, 2*8(sp)      # save user stack pointer into the TrapContext
-
-    ld ra, 35*8(sp)
-    ld s0, 36*8(sp)
-    ld s1, 37*8(sp)
-    ld s2, 38*8(sp)
-    ld s3, 39*8(sp)
-    ld s4, 40*8(sp)
-    ld s5, 41*8(sp)
-    ld s6, 42*8(sp)
-    ld s7, 43*8(sp)
-    ld s8, 44*8(sp)
-    ld s9, 45*8(sp)
-    ld s10, 46*8(sp)
-    ld s11, 47*8(sp)
-
-    ld fp, 48*8(sp)
-    ld tp, 49*8(sp)
-
-    ld sp, 34*8(sp)
-    ret
-
-# a0: pointer to TrapContext in user space (constant)
-return_to_user:
-    # sscratch store the TrapContext's address
-    csrw sscratch, a0
-
-    # offset in TrapContext's order
-    sd sp, 34*8(a0)
-    sd ra, 35*8(a0)
-    sd s0, 36*8(a0)
-    sd s1, 37*8(a0) 
-    sd s2, 38*8(a0)
-    sd s3, 39*8(a0)
-    sd s4, 40*8(a0)
-    sd s5, 41*8(a0)
-    sd s6, 42*8(a0)
-    sd s7, 43*8(a0)
-    sd s8, 44*8(a0)
-    sd s9, 45*8(a0)
-    sd s10, 46*8(a0)
-    sd s11, 47*8(a0)
-    sd fp, 48*8(a0)
-    sd tp, 49*8(a0)
-
-    mv sp, a0
-    # now sp points to TrapContext in kernel space
-
-    # restore sstatus and sepc
-    ld t0, 32*8(sp)
-    ld t1, 33*8(sp)
-    csrw sstatus, t0
-    csrw sepc, t1
-
-    # save x* expect x0 and sp
-    ld x1, 1*8(sp)
-    .set n, 3
-    .rept 29
-        LOAD_GP %n
-        .set n, n+1
-    .endr
-    ld sp, 2*8(sp)
-
-    sret

+ 0 - 32
arch/src/riscv64/interrupt/trap.rs

@@ -1,32 +0,0 @@
-use super::setup_kernel_trap;
-
-use riscv::register::{scause, sepc, stval};
-
-/// TODO:
-/// kernel_trap_entry, 暂时不知道要干什么,大概是处理一下原因,然后跳到default handler
-/// user_trap_entry, 大概是一样的
-/// trap_return, 估计不是在这里写,还不太清楚
-
-#[no_mangle]
-pub fn kernel_trap_entry() {
-    let stval = stval::read();
-    let scause = scause::read();
-    let sepc = sepc::read();
-    let cause = scause.cause();
-
-    match scause.cause() {
-        scause::Trap::Interrupt(_) => todo!(),
-        scause::Trap::Exception(_) => todo!(),
-    }
-}
-
-#[no_mangle]
-pub fn user_trap_entry() {
-    setup_kernel_trap();
-
-}
-
-#[no_mangle]
-pub fn trap_return() {
-
-}

+ 0 - 50
arch/src/riscv64/io.rs

@@ -1,50 +0,0 @@
-use core::ptr::{read_volatile, write_volatile};
-
-pub fn inb(_addr: u16) -> u8 {
-    /*unsafe {
-        read_volatile(addr as *const u8)
-    }*/
-    0
-}
-
-pub fn inw(addr: usize) -> u16 {
-    unsafe {
-        read_volatile(addr as *const u16)
-    }
-}
-
-pub fn inl(addr: usize) -> u32 {
-    unsafe {
-        read_volatile(addr as *const u32)
-    }
-}
-
-pub fn inu64(addr: usize) -> u64 {
-    unsafe {
-        read_volatile(addr as *const u64)
-    }
-}
-
-pub fn outb(addr: u16, data: u8) {
-    unsafe {
-        write_volatile(addr as *mut u8, data)
-    }
-}
-
-pub fn outw(addr: usize, data: u16) {
-    unsafe {
-        write_volatile(addr as *mut u16, data)
-    }
-}
-
-pub fn outl(addr: usize, data: u32) {
-    unsafe {
-        write_volatile(addr as *mut u32, data)
-    }
-}
-
-pub fn outu64(addr: usize, data: u64) {
-    unsafe {
-        write_volatile(addr as *mut u64, data)
-    }
-}

+ 0 - 170
arch/src/riscv64/kernel.ld

@@ -1,170 +0,0 @@
-OUTPUT_FORMAT(riscv)
-ENTRY(_start)
-
-RAM = 0x80200000;
-
-MEMORY
-{
-    KBSS          (w)  : org = 0xffffffff00200000, len = 2M
-    KIMAGE        (wx) : org = 0xffffffff80200000, len = 2M
-    KPERCPU       (w)  : org = 0x0000000000000000, len = 128K
-}
-
-SECTIONS
-{
-    .text : AT(RAM)
-    {
-        TEXT_START = .;
-        *(.text.entry)
-        *(.text)
-        *(.text*)
-
-        . = ALIGN(0x1000);
-        TEXT_END = .;
-    } > KIMAGE
-
-    TEXT_PAGES = (TEXT_END - TEXT_START) / 0x1000;
-
-    .rodata :
-        AT(LOADADDR(.text) + SIZEOF(.text))
-    {
-        RODATA_START = .;
-        *(.rodata)
-        *(.rodata*)
-
-        . = ALIGN(16);
-        start_ctors = .;
-        KEEP(*(.init_array));
-        KEEP(*(SORT_BY_INIT_PRIORITY(.init_array*)));
-        KEEP(*(.ctors));
-        KEEP(*(SORT_BY_INIT_PRIORITY(.ctors*)));
-        end_ctors = .;
-
-        . = ALIGN(16);
-        _fix_start = .;
-        KEEP(*(.fix));
-        _fix_end = .;
-
-        . = ALIGN(16);
-        BSS_ADDR = .;
-        QUAD(ABSOLUTE(BSS_START));
-        BSS_LENGTH = .;
-        QUAD(BSS_END - BSS_START);
-        FIX_START = .;
-        QUAD(ABSOLUTE(_fix_start));
-        FIX_END = .;
-        QUAD(ABSOLUTE(_fix_end));
-        PERCPU_PAGES = .;
-        QUAD(_PERCPU_PAGES);
-
-        . = ALIGN(0x1000);
-        RODATA_END = .;
-    } > KIMAGE
-
-    RODATA_PAGES = (RODATA_END - RODATA_START) / 0x1000;
-
-    .data : AT(LOADADDR(.rodata) + SIZEOF(.rodata))
-    {
-        DATA_START = .;
-        *(.data)
-        *(.data*)
-
-        *(.got)
-        *(.got.plt)
-
-        . = . + 4;
-        . = ALIGN(0x1000) - 4;
-        LONG(KERNEL_MAGIC);
-        DATA_END = .;
-    } > KIMAGE
-
-    DATA_PAGES = (DATA_END - DATA_START) / 0x1000;
-
-    _PERCPU_DATA_START = .;
-    .percpu 0 : AT(LOADADDR(.data) + SIZEOF(.data))
-    {
-        PERCPU_START = .;
-        QUAD(0); /* Reserved for x86 percpu pointer */
-        QUAD(0);
-
-        *(.percpu .percpu*)
-
-        . = ALIGN(0x1000);
-        PERCPU_END = .;
-    } > KPERCPU
-    _PERCPU_LENGTH = PERCPU_END - PERCPU_START;
-
-    _PERCPU_PAGES = _PERCPU_LENGTH / 0x1000;
-
-    .bss :
-    {
-        BSS_STACK = .;
-        *(.bss.stack)
-        BSS_START = .;
-        *(.bss)
-        *(.bss*)
-
-        . = ALIGN(0x1000);
-        BSS_END = .;
-    } > KBSS
-
-    KIMAGE_PAGES = TEXT_PAGES + RODATA_PAGES + _PERCPU_PAGES + DATA_PAGES;
-    BSS_PAGES = (BSS_END - BSS_START) / 0x1000;
-    KERNEL_MAGIC = 0x01145140;
-
-    KIMAGE_32K_COUNT = (KIMAGE_PAGES * 0x1000 + 32 * 1024 - 1) / (32 * 1024);
-
-    .eh_frame :
-        AT(LOADADDR(.percpu) + SIZEOF(.percpu))
-    {
-        KEEP(*(.eh_frame*))
-        . = ALIGN(0x1000);
-    } > KIMAGE
-
-    /* Stabs debugging sections.  */
-    .stab          0 : { KEEP(*(.stab)); }
-    .stabstr       0 : { KEEP(*(.stabstr)); }
-    .stab.excl     0 : { KEEP(*(.stab.excl)); }
-    .stab.exclstr  0 : { KEEP(*(.stab.exclstr)); }
-    .stab.index    0 : { KEEP(*(.stab.index)); }
-    .stab.indexstr 0 : { KEEP(*(.stab.indexstr)); }
-    .comment       0 : { KEEP(*(.comment)); }
-    /* DWARF debug sections.
-       Symbols in the DWARF debugging sections are relative to the beginning
-       of the section so we begin them at 0.  */
-    /* DWARF 1 */
-    .debug          0 : { KEEP(*(.debug)); }
-    .line           0 : { KEEP(*(.line)); }
-    /* GNU DWARF 1 extensions */
-    .debug_srcinfo  0 : { KEEP(*(.debug_srcinfo)); }
-    .debug_sfnames  0 : { KEEP(*(.debug_sfnames)); }
-    /* DWARF 1.1 and DWARF 2 */
-    .debug_aranges  0 : { KEEP(*(.debug_aranges)); }
-    .debug_pubnames 0 : { KEEP(*(.debug_pubnames)); }
-    /* DWARF 2 */
-    .debug_info     0 : { KEEP(*(.debug_info)); }
-    .debug_abbrev   0 : { KEEP(*(.debug_abbrev)); }
-    .debug_line     0 : { KEEP(*(.debug_line)); }
-    .debug_frame    0 : { KEEP(*(.debug_frame)); }
-    .debug_str      0 : { KEEP(*(.debug_str)); }
-    .debug_loc      0 : { KEEP(*(.debug_loc)); }
-    .debug_macinfo  0 : { KEEP(*(.debug_macinfo)); }
-    /* SGI/MIPS DWARF 2 extensions */
-    .debug_weaknames 0 : { KEEP(*(.debug_weaknames)); }
-    .debug_funcnames 0 : { KEEP(*(.debug_funcnames)); }
-    .debug_typenames 0 : { KEEP(*(.debug_typenames)); }
-    .debug_varnames  0 : { KEEP(*(.debug_varnames)); }
-
-    /* DWARF Other */
-    .debug_ranges  0 : { KEEP(*(.debug_ranges)); }
-    .debug_line_str 0 : { KEEP(*(.debug_line_str)); }
-    /* Rust stuff */
-
-    /DISCARD/ :
-    {
-        *(.fini_array*)
-        *(.note*)
-        *(.dtors*)
-        *(.debug_gdb_scripts*)
-    }
-}

+ 0 - 214
arch/src/riscv64/mm.rs

@@ -1,214 +0,0 @@
-use core::{marker::PhantomData, ptr::NonNull};
-use eonix_mm::{
-    page_table::{
-        PageAttribute, PageTableLevel, PagingMode, RawAttribute, RawPageTable, TableAttribute, PTE,
-    },
-    paging::{PageBlock, PFN},
-};
-use riscv::{asm::sfence_vma_all, register::satp};
-
-use super::config::mm::ROOT_PAGE_TABLE_PFN;
-
-pub const PAGE_TABLE_BASE: PFN = PFN::from_val(ROOT_PAGE_TABLE_PFN);
-
-pub const PA_V: u64 = 0b1 << 0;
-pub const PA_R: u64 = 0b1 << 1;
-pub const PA_W: u64 = 0b1 << 2;
-pub const PA_X: u64 = 0b1 << 3;
-pub const PA_U: u64 = 0b1 << 4;
-pub const PA_G: u64 = 0b1 << 5;
-pub const PA_A: u64 = 0b1 << 6;
-pub const PA_D: u64 = 0b1 << 7;
-
-// in RSW
-pub const PA_COW: u64 = 0b1 << 8;
-pub const PA_MMAP: u64 = 0b1 << 9;
-
-#[allow(dead_code)]
-pub const PA_SHIFT: u64 = 10;
-// Bit 0-9 (V, R, W, X, U, G, A, D, RSW)
-#[allow(dead_code)]
-pub const PA_FLAGS_MASK: u64 = 0x3FF; // 0b11_1111_1111
-
-#[repr(transparent)]
-#[derive(Clone, Copy)]
-pub struct PTE64(pub u64);
-
-#[derive(Clone, Copy)]
-pub struct PageAttribute64(u64);
-
-pub struct RawPageTableSv39<'a>(NonNull<PTE64>, PhantomData<&'a ()>);
-
-pub struct PagingModeSv39;
-
-impl PTE for PTE64 {
-    type Attr = PageAttribute64;
-
-    fn set(&mut self, pfn: PFN, attr: Self::Attr) {
-        self.0 = (usize::from(pfn) << PA_SHIFT) as u64 | attr.0;
-    }
-
-    fn get(&self) -> (PFN, Self::Attr) {
-        let pfn = PFN::from(self.0 as usize >> PA_SHIFT);
-        let attr = PageAttribute64(self.0 & PA_FLAGS_MASK);
-        (pfn, attr)
-    }
-}
-
-impl PagingMode for PagingModeSv39 {
-    type Entry = PTE64;
-    type RawTable<'a> = RawPageTableSv39<'a>;
-    const LEVELS: &'static [PageTableLevel] = &[
-        PageTableLevel::new(30, 9),
-        PageTableLevel::new(21, 9),
-        PageTableLevel::new(12, 9),
-    ];
-    const KERNEL_ROOT_TABLE_PFN: PFN = PAGE_TABLE_BASE;
-}
-
-impl<'a> RawPageTable<'a> for RawPageTableSv39<'a> {
-    type Entry = PTE64;
-
-    fn index(&self, index: u16) -> &'a Self::Entry {
-        unsafe { self.0.add(index as usize).as_ref() }
-    }
-
-    fn index_mut(&mut self, index: u16) -> &'a mut Self::Entry {
-        unsafe { self.0.add(index as usize).as_mut() }
-    }
-
-    unsafe fn from_ptr(ptr: NonNull<PageBlock>) -> Self {
-        Self(ptr.cast(), PhantomData)
-    }
-}
-
-impl RawAttribute for PageAttribute64 {
-    fn null() -> Self {
-        Self(0)
-    }
-
-    fn as_table_attr(self) -> Option<TableAttribute> {
-        let mut table_attr = TableAttribute::empty();
-
-        if self.0 & (PA_R | PA_W | PA_X) != 0 {
-            panic!("Encountered a huge page while parsing table attributes");
-        }
-
-        if self.0 & PA_V != 0 {
-            table_attr |= TableAttribute::PRESENT;
-        }
-        if self.0 & PA_G != 0 {
-            table_attr |= TableAttribute::GLOBAL;
-        }
-        if self.0 & PA_U != 0 {
-            table_attr |= TableAttribute::USER;
-        }
-        if self.0 & PA_A != 0 {
-            table_attr |= TableAttribute::ACCESSED;
-        }
-
-        Some(table_attr)
-    }
-
-    fn as_page_attr(self) -> Option<PageAttribute> {
-        let mut page_attr = PageAttribute::empty();
-
-        if self.0 & (PA_R | PA_W | PA_X) == 0 {
-            panic!("Invalid page attribute combination");
-        }
-
-        if self.0 & PA_V != 0 {
-            page_attr |= PageAttribute::PRESENT;
-        }
-
-        if self.0 & PA_R != 0 {
-            page_attr |= PageAttribute::READ;
-        }
-
-        if self.0 & PA_W != 0 {
-            page_attr |= PageAttribute::WRITE;
-        }
-
-        if self.0 & PA_X != 0 {
-            page_attr |= PageAttribute::EXECUTE;
-        }
-
-        if self.0 & PA_U != 0 {
-            page_attr |= PageAttribute::USER;
-        }
-
-        if self.0 & PA_A != 0 {
-            page_attr |= PageAttribute::ACCESSED;
-        }
-
-        if self.0 & PA_D != 0 {
-            page_attr |= PageAttribute::DIRTY;
-        }
-
-        if self.0 & PA_G != 0 {
-            page_attr |= PageAttribute::GLOBAL;
-        }
-
-        if self.0 & PA_COW != 0 {
-            page_attr |= PageAttribute::COPY_ON_WRITE;
-        }
-
-        if self.0 & PA_MMAP != 0 {
-            page_attr |= PageAttribute::MAPPED;
-        }
-
-        /*if self.0 & PA_ANON != 0 {
-            page_attr |= PageAttribute::ANONYMOUS;
-        }*/
-
-        Some(page_attr)
-    }
-
-    fn from_table_attr(table_attr: TableAttribute) -> Self {
-        let mut raw_attr = 0;
-
-        for attr in table_attr.iter() {
-            match attr {
-                TableAttribute::PRESENT => raw_attr |= PA_V,
-                TableAttribute::GLOBAL => raw_attr |= PA_G,
-                TableAttribute::USER => raw_attr |= PA_U,
-                TableAttribute::ACCESSED => raw_attr |= PA_A,
-                _ => unreachable!("Invalid table attribute"),
-            }
-        }
-
-        Self(raw_attr)
-    }
-
-    fn from_page_attr(page_attr: PageAttribute) -> Self {
-        let mut raw_attr = 0;
-
-        for attr in page_attr.iter() {
-            match attr {
-                PageAttribute::PRESENT => raw_attr |= PA_V,
-                PageAttribute::READ => raw_attr |= PA_R,
-                PageAttribute::WRITE => raw_attr |= PA_W,
-                PageAttribute::EXECUTE => raw_attr |= PA_X,
-                PageAttribute::USER => raw_attr |= PA_U,
-                PageAttribute::ACCESSED => raw_attr |= PA_A,
-                PageAttribute::DIRTY => raw_attr |= PA_D,
-                PageAttribute::GLOBAL => raw_attr |= PA_G,
-                PageAttribute::COPY_ON_WRITE => raw_attr |= PA_COW,
-                PageAttribute::MAPPED => raw_attr |= PA_MMAP,
-                PageAttribute::ANONYMOUS => {},
-                _ => unreachable!("Invalid page attribute"),
-            }
-        }
-
-        Self(raw_attr)
-    }
-}
-
-pub type DefaultPagingMode = PagingModeSv39;
-
-pub fn setup_kernel_satp() {
-    unsafe {
-        satp::set(satp::Mode::Sv48, 0, PFN::from(ROOT_PAGE_TABLE_PFN).into());
-    }
-    sfence_vma_all();
-}

+ 10 - 12
arch/src/riscv64/mod.rs

@@ -1,13 +1,17 @@
 use core::arch::asm;
 
-use eonix_mm::{address::{Addr, PAddr, VAddr}, paging::PFN};
-use riscv::{asm::{sfence_vma, sfence_vma_all}, register::{satp, stval}};
+use eonix_mm::{
+    address::{Addr, PAddr, VAddr},
+    paging::PFN,
+};
+use riscv::{
+    asm::{sfence_vma, sfence_vma_all},
+    register::{satp, stval},
+};
 
-mod io;
 mod fence;
 mod fpu;
 
-pub use io::*;
 pub use fence::*;
 pub use fpu::*;
 
@@ -44,19 +48,13 @@ pub fn get_page_fault_address() -> VAddr {
 #[inline(always)]
 pub fn halt() {
     unsafe {
-        asm!(
-            "wfi",
-            options(nomem, nostack)
-        );
+        asm!("wfi", options(nomem, nostack));
     }
 }
 
 #[inline(always)]
 pub fn pause() {
     unsafe {
-        asm!(
-            "nop",
-            options(nomem, nostack)
-        );
+        asm!("nop", options(nomem, nostack));
     }
 }

+ 1 - 1
crates/eonix_hal/Cargo.toml

@@ -22,6 +22,6 @@ intrusive_list = { path = "../intrusive_list" }
 buddy_allocator = { path = "../buddy_allocator" }
 sbi = "0.3.0"
 riscv = { version = "0.13.0", features = ["s-mode"] }
-spin = "0.10.0"
+riscv-peripheral = { version = "0.3.0" }
 fdt = "0.1"
 bitflags = "2.6.0"

+ 85 - 75
crates/eonix_hal/src/arch/riscv64/bootstrap.rs

@@ -1,11 +1,17 @@
+use super::{
+    config::{self, mm::*},
+    console::write_str,
+};
 use crate::{
     arch::{
-        cpu::CPU, fdt::init_dtb_and_fdt, mm::{ArchPhysAccess, PageAttribute64, PagingModeSv39, GLOBAL_PAGE_TABLE, V_KERNEL_BSS_START}
+        cpu::CPU,
+        fdt::{init_dtb_and_fdt, FdtExt},
+        mm::{ArchPhysAccess, FreeRam, PageAttribute64, GLOBAL_PAGE_TABLE},
     },
     bootstrap::BootStrapData,
     mm::{ArchMemory, ArchPagingMode, BasicPageAlloc, BasicPageAllocRef, ScopedAllocator},
 };
-use riscv::{asm::sfence_vma_all, register::{satp, sstatus::{self, FS}}};
+use core::arch::naked_asm;
 use core::{
     alloc::Allocator,
     arch::asm,
@@ -14,108 +20,117 @@ use core::{
 };
 use eonix_hal_traits::mm::Memory;
 use eonix_mm::{
-    address::{Addr as _, PAddr, PRange, VAddr, VRange},
+    address::{Addr as _, PAddr, PRange, PhysAccess, VAddr, VRange},
     page_table::{PageAttribute, PagingMode, PTE as _},
     paging::{Page, PageAccess, PageAlloc, PAGE_SIZE, PFN},
 };
 use eonix_percpu::PercpuArea;
-
-use super::{
-    config::{self, mm::*},
-    fdt::get_num_harts,
-    console::write_str,
+use fdt::Fdt;
+use riscv::{
+    asm::sfence_vma_all,
+    register::{
+        satp,
+        sstatus::{self, FS},
+    },
 };
 
-use core::arch::naked_asm;
+#[unsafe(link_section = ".bootstrap.stack")]
+static BOOT_STACK: [u8; 4096 * 16] = [0; 4096 * 16];
 
-#[unsafe(link_section = ".bootstack")]
-static mut BOOT_STACK: [u8; 4096 * 16] = [0; 4096 * 16];
+static BOOT_STACK_START: &'static [u8; 4096 * 16] = &BOOT_STACK;
 
 #[repr(C, align(4096))]
-struct BootPageTable([u64; PTES_PER_PAGE]);
+struct PageTable([u64; PTES_PER_PAGE]);
 
 /// map 0x8000 0000 to itself and 0xffff ffff 8000 0000
-#[unsafe(link_section = ".bootdata")]
-static mut BOOT_PAGE_TABLE: BootPageTable = {
+#[unsafe(link_section = ".bootstrap.page_table.1")]
+static BOOT_PAGE_TABLE: PageTable = {
     let mut arr: [u64; PTES_PER_PAGE] = [0; PTES_PER_PAGE];
-    arr[2] = (0x80000 << 10) | 0xcf;
-    arr[510] = (0x80000 << 10) | 0xcf;
-    BootPageTable(arr)
+    arr[0] = 0 | 0x2f;
+    arr[510] = 0 | 0x2f;
+    arr[511] = (0x80202 << 10) | 0x21;
+
+    PageTable(arr)
 };
 
-static AP_COUNT: AtomicUsize = AtomicUsize::new(0);
-static AP_STACK: AtomicUsize = AtomicUsize::new(0);
-static AP_SEM: AtomicBool = AtomicBool::new(false);
+#[unsafe(link_section = ".bootstrap.page_table.2")]
+#[used]
+static PT1: PageTable = {
+    let mut arr: [u64; PTES_PER_PAGE] = [0; PTES_PER_PAGE];
+    arr[510] = (0x80000 << 10) | 0x2f;
 
-unsafe extern "Rust" {
-    fn kernel_init();
-}
+    PageTable(arr)
+};
 
 /// bootstrap in rust
 #[unsafe(naked)]
 #[unsafe(no_mangle)]
-#[unsafe(link_section = ".text.entry")]
+#[unsafe(link_section = ".bootstrap.entry")]
 unsafe extern "C" fn _start(hart_id: usize, dtb_addr: usize) -> ! {
     naked_asm!(
         "
-            la    sp, {boot_stack}
-            la    t0, {page_table}
+            ld    sp, 2f
+            li    t0, 0x10000
+            add   sp, sp, t0
+            ld    t0, 3f
             srli  t0, t0, 12
-            li    t1, 8 << 60
+            li    t1, 9 << 60
             or    t0, t0, t1
             csrw  satp, t0
             sfence.vma
-            li    t2, {virt_ram_offset}
-            or    sp, sp, t2
-            la    t3, riscv64_start
-            or    t3, t3, t2
-            jalr  t3                      // call riscv64_start
+            ld    t0, 4f
+            jalr  t0                      // call riscv64_start
+
+            .pushsection .bootstrap.data, \"aw\", @progbits
+            2:
+            .8byte {boot_stack}
+            3:
+            .8byte {page_table}
+            4:
+            .8byte {riscv64_start}
+            .popsection
         ",
         boot_stack = sym BOOT_STACK,
         page_table = sym BOOT_PAGE_TABLE,
-        virt_ram_offset = const KIMAGE_OFFSET,
+        riscv64_start = sym riscv64_start,
     )
 }
 
-/// TODO: 
-/// linker,现在VMA和LMA不对
-/// 设置中断
+/// TODO:
 /// 启动所有的cpu
-#[unsafe(no_mangle)]
-pub unsafe extern "C" fn riscv64_start(hart_id: usize, dtb_addr: usize) -> ! {
-    write_str("hello\n");
+pub unsafe extern "C" fn riscv64_start(hart_id: usize, dtb_addr: PAddr) -> ! {
+    enable_fpu();
+    let fdt = Fdt::from_ptr(ArchPhysAccess::as_ptr(dtb_addr).as_ptr())
+        .expect("Failed to parse DTB from static memory.");
 
     let real_allocator = RefCell::new(BasicPageAlloc::new());
     let alloc = BasicPageAllocRef::new(&real_allocator);
 
-    for range in ArchMemory::free_ram() {
+    for range in fdt.present_ram().free_ram() {
         real_allocator.borrow_mut().add_range(range);
     }
 
     setup_kernel_page_table(&alloc);
     unsafe {
-        init_dtb_and_fdt(dtb_addr)
-    };
-    enable_sse();
-    
-    let num_harts = get_num_harts();
-    config::smp::set_num_harts(num_harts);
+        init_dtb_and_fdt(dtb_addr);
+    }
 
     setup_cpu(&alloc, hart_id);
 
     // TODO: set up interrupt, smp
-    //ScopedAllocator::new(&mut [0; 1024])
-    //    .with_alloc(|mem_alloc| bootstrap_smp(mem_alloc, &real_allocator));
+    ScopedAllocator::new(&mut [0; 1024])
+        .with_alloc(|mem_alloc| bootstrap_smp(mem_alloc, &real_allocator));
 
     unsafe extern "Rust" {
         fn _eonix_hal_main(_: BootStrapData) -> !;
     }
 
-    let start = &raw mut BOOT_STACK as usize + KIMAGE_OFFSET;
+    let start = unsafe {
+        ((&BOOT_STACK_START) as *const &'static [u8; 4096 * 16]).read_volatile() as *const _
+            as usize
+    };
     let bootstrap_data = BootStrapData {
-        early_stack: PRange::new(
-            PAddr::from(start),
-            PAddr::from(start + 4096 * 16)),
+        early_stack: PRange::new(PAddr::from(start), PAddr::from(start + 4096 * 16)),
         allocator: Some(real_allocator),
     };
 
@@ -131,7 +146,7 @@ unsafe extern "C" {
 
 /// TODO:
 /// 对kernel image添加更细的控制,或者不加也行
-pub fn setup_kernel_page_table(alloc: impl PageAlloc) {
+fn setup_kernel_page_table(alloc: impl PageAlloc) {
     let global_page_table = &GLOBAL_PAGE_TABLE;
 
     let attr = PageAttribute::WRITE
@@ -140,40 +155,33 @@ pub fn setup_kernel_page_table(alloc: impl PageAlloc) {
         | PageAttribute::GLOBAL
         | PageAttribute::PRESENT;
 
-    // Map Physical memory 128Gb, add a 0xFFFF_FFC0_0000_0000 offset
-    // use 1 Gb size page
-    for (idx, pte) in global_page_table
-        .iter_kernel_levels(VRange::from(VAddr::from(PHYS_MAP_VIRT)).grow(MEMORY_SIZE), &PagingModeSv39::LEVELS[..=0])
-        .enumerate()
-    {
-        pte.set(PFN::from(idx * 0x40000), PageAttribute64::from(attr));
-    }
-
-    // Map 2 MB kernel image
-    for (idx, pte) in global_page_table
-        .iter_kernel(VRange::from(VAddr::from(KIMAGE_VIRT_BASE)).grow(KIMAGE_PAGES as usize * 0x1000))
-        .enumerate()
-    {
-        pte.set(PFN::from(idx + 0x80200), PageAttribute64::from(attr));
-    }
+    const KERNEL_BSS_START: VAddr = VAddr::from(0xffffffff40000000);
 
     // Map kernel BSS
     for pte in global_page_table.iter_kernel_in(
-        VRange::from(V_KERNEL_BSS_START).grow(BSS_LENGTH as usize),
+        VRange::from(KERNEL_BSS_START).grow(BSS_LENGTH as usize),
         ArchPagingMode::LEVELS,
         &alloc,
     ) {
         let page = Page::alloc_in(&alloc);
+
+        let attr = {
+            let mut attr = attr.clone();
+            attr.remove(PageAttribute::EXECUTE);
+            attr
+        };
         pte.set(page.into_raw(), attr.into());
     }
 
+    sfence_vma_all();
+
     unsafe {
-        core::ptr::write_bytes(V_KERNEL_BSS_START.addr() as *mut (), 0, BSS_LENGTH as usize);
+        core::ptr::write_bytes(KERNEL_BSS_START.addr() as *mut (), 0, BSS_LENGTH as usize);
     }
 
     unsafe {
         satp::set(
-            satp::Mode::Sv39,
+            satp::Mode::Sv48,
             0,
             usize::from(PFN::from(global_page_table.addr())),
         );
@@ -181,7 +189,7 @@ pub fn setup_kernel_page_table(alloc: impl PageAlloc) {
     sfence_vma_all();
 }
 
-pub fn enable_sse() {
+fn enable_fpu() {
     unsafe {
         // FS (Floating-point Status) Initial (0b01)
         sstatus::set_fs(FS::Initial);
@@ -216,11 +224,13 @@ fn setup_cpu(alloc: impl PageAlloc, hart_id: usize) {
     unsafe {
         cpu.as_mut().init(hart_id);
     }
-    
+
     percpu_area.register(cpu.cpuid());
 }
 
 /// TODO
-fn bootstrap_smp(alloc: impl Allocator, page_alloc: &RefCell<BasicPageAlloc>) {
+fn bootstrap_smp(alloc: impl Allocator, page_alloc: &RefCell<BasicPageAlloc>) {}
 
+pub fn early_console_write(s: &str) {
+    write_str(s);
 }

+ 4 - 27
crates/eonix_hal/src/arch/riscv64/config.rs

@@ -1,7 +1,7 @@
 /// mm
 pub mod mm {
-    pub const ROOT_PAGE_TABLE_PHYS_ADDR: usize = 0x8040_0000;
-    pub const PHYS_MAP_VIRT: usize = 0xffff_ffc0_0000_0000;
+    pub const ROOT_PAGE_TABLE_PHYS_ADDR: usize = 0x8020_1000;
+    pub const PHYS_MAP_VIRT: usize = 0xffff_ff00_0000_0000;
     pub const KIMAGE_PHYS_BASE: usize = 0x8020_0000;
     pub const KIMAGE_OFFSET: usize = 0xffff_ffff_0000_0000;
     pub const MMIO_VIRT_BASE: usize = KIMAGE_OFFSET;
@@ -15,28 +15,6 @@ pub mod mm {
     pub const PTES_PER_PAGE: usize = PAGE_SIZE / PTE_SIZE;
     pub const ROOT_PAGE_TABLE_PFN: usize = ROOT_PAGE_TABLE_PHYS_ADDR >> 12;
     pub const PAGE_TABLE_PHYS_END: usize = 0x8080_0000;
-
-    #[derive(Clone, Copy)]
-    pub enum PageSize {
-        _4KbPage = 4096,
-        _2MbPage = 2 * 1024 * 1024,
-        _1GbPage = 1 * 1024 * 1024 * 1024,
-    }
-}
-
-/// smp
-pub mod smp {
-    use spin::Once;
-
-    pub static NUM_HARTS: Once<usize> = Once::new();
-
-    pub fn set_num_harts(num: usize) {
-        NUM_HARTS.call_once(|| num);
-    }
-
-    pub fn get_num_harts() -> usize {
-        *NUM_HARTS.get().expect("NUM_HARTS should be initialized by now")
-    }
 }
 
 pub mod platform {
@@ -60,10 +38,9 @@ pub mod platform {
         // CLINT (Core Local Interruptor) memory-mapped registers
         // Base address for CLINT on QEMU virt platform
         pub const CLINT_BASE: usize = 0x200_0000;
-        pub const CLINT_MSIP_OFFSET: usize = 0x0000;      // Machine-mode Software Interrupt Pending (MSIP)
-        pub const CLINT_MTIMECMP_OFFSET: usize = 0x4000;  // Machine-mode Timer Compare (MTIMECMP)
+        pub const CLINT_MSIP_OFFSET: usize = 0x0000; // Machine-mode Software Interrupt Pending (MSIP)
+        pub const CLINT_MTIMECMP_OFFSET: usize = 0x4000; // Machine-mode Timer Compare (MTIMECMP)
         pub const CLINT_MTIME_OFFSET: usize = 0xBFF8;
         pub const CPU_FREQ_HZ: u64 = 10_000_000;
     }
 }
-

+ 12 - 29
crates/eonix_hal/src/arch/riscv64/context.rs

@@ -10,7 +10,6 @@ pub struct TaskContext {
     s: [u64; 12],
     sp: u64,
     ra: u64,
-    sepc: u64,
     sstatus: u64,
 }
 
@@ -20,7 +19,7 @@ impl RawTaskContext for TaskContext {
     }
 
     fn set_program_counter(&mut self, pc: usize) {
-        self.sepc = pc as u64;
+        self.ra = pc as u64;
     }
 
     fn set_stack_pointer(&mut self, sp: usize) {
@@ -44,18 +43,14 @@ impl RawTaskContext for TaskContext {
     }
 
     fn call(&mut self, func: unsafe extern "C" fn(usize) -> !, arg: usize) {
-        self.set_program_counter(Self::do_call as usize);
-
         self.s[0] = func as u64;
         self.s[1] = arg as u64;
 
-        self.ra = 0;
+        self.set_program_counter(Self::do_call as usize);
     }
 
     unsafe extern "C" fn switch(from: &mut Self, to: &mut Self) {
-        unsafe {
-            Self::__task_context_switch(from, to)
-        }
+        unsafe { Self::__task_context_switch(from, to) }
     }
 }
 
@@ -65,7 +60,6 @@ impl TaskContext {
             s: [0; 12],
             sp: 0,
             ra: 0,
-            sepc: 0,
             sstatus: 0,
         }
     }
@@ -123,12 +117,9 @@ impl TaskContext {
             "sd  s11, 88(a0)",
             "sd   sp, 96(a0)",
             "sd   ra, 104(a0)",
-            "csrr s0, sstatus",
-            "sd   s0, 112(a0)", // Store sstatus at offset 112
-            "csrr s0, sepc",
-            "sd   s0, 120(a0)", // Store sepc at offset 120
-
-            // Load next task's callee-saved registers from `to` context
+            "csrr t0, sstatus",
+            "sd   t0, 112(a0)",
+            "",
             "ld   s0, 0(a1)",
             "ld   s1, 8(a1)",
             "ld   s2, 16(a1)",
@@ -145,10 +136,7 @@ impl TaskContext {
             "ld   ra, 104(a1)",
             "ld   t0, 112(a1)",
             "csrw sstatus, t0",
-            "ld   t0, 120(a1)",
-            "csrw sepc, t0",
-
-            "sret",
+            "ret",
         );
     }
 
@@ -159,23 +147,18 @@ impl TaskContext {
     }
 
     #[unsafe(naked)]
-    #[unsafe(no_mangle)]
     /// Maximum of 5 arguments supported.
     unsafe extern "C" fn do_call() -> ! {
         naked_asm!(
-            // Move function pointer.
-            "mv   t0, s0",
-
-            // Move arguments.
-            "mv   a0, s1",
+            "mv   t0, s0", // Function pointer in s0.
+            "mv   a0, s1", // Args
             "mv   a1, s2",
             "mv   a2, s3",
             "mv   a3, s4",
             "mv   a4, s5",
-
-            "mv   s0, zero", // Set s0 (fp) to 0.
-
-            "jr   t0", // Jump to t0.
+            "mv   fp, zero", // Set frame pointer to 0.
+            "mv   ra, zero",
+            "jr   t0",
         );
     }
 }

+ 16 - 114
crates/eonix_hal/src/arch/riscv64/cpu.rs

@@ -1,27 +1,15 @@
+use super::{interrupt::InterruptControl, trap::setup_trap};
+use crate::arch::fdt::{FdtExt, FDT};
 use core::pin::Pin;
-use riscv::register::{
-    mhartid,
-    sscratch,
-    sstatus
-};
-use sbi::PhysicalAddress;
 use eonix_preempt::PreemptGuard;
 use eonix_sync_base::LazyLock;
-
-/// TODO:
-/// CPU 的一些函数
-/// 
+use riscv::register::{mhartid, sscratch, sstatus};
+use riscv_peripheral::plic::PLIC;
+use sbi::PhysicalAddress;
 
 #[eonix_percpu::define_percpu]
 static LOCAL_CPU: LazyLock<CPU> = LazyLock::new(CPU::new);
 
-use super::{
-    config::smp::get_num_harts,
-    mm::setup_kernel_satp,
-    trap::setup_trap,
-    interrupt::InterruptControl
-};
-
 #[derive(Debug, Clone)]
 pub enum UserTLS {
     Base(u32),
@@ -42,10 +30,9 @@ impl UserTLS {
 
 impl CPU {
     pub fn new() -> Self {
-        let hart_id = 0;
         Self {
-            hart_id: hart_id,
-            interrupt: InterruptControl::new(hart_id),
+            hart_id: 0,
+            interrupt: InterruptControl::new(),
         }
     }
 
@@ -54,46 +41,27 @@ impl CPU {
     /// # Safety
     /// This function performs low-level hardware initialization and should
     /// only be called once per Hart during its boot sequence.
-    pub unsafe fn init(self: Pin<&mut Self>, hart_id: usize) {
-        let self_mut = self.get_unchecked_mut();
-        self_mut.hart_id = hart_id;
-
-        sscratch::write(self_mut.hart_id as usize);
+    pub unsafe fn init(mut self: Pin<&mut Self>, hart_id: usize) {
+        let me = self.as_mut().get_unchecked_mut();
+        me.hart_id = hart_id;
 
         setup_trap();
 
-        // CLINT, 10_000 ms
-        self_mut.interrupt.setup_timer(10_000);
+        let interrupt = self.map_unchecked_mut(|me| &mut me.interrupt);
+        interrupt.init();
 
-        // Supervisor Mode Status Register (sstatus)
-        // SUM (Supervisor User Memory access): support S-mode access user memory
-        // MXR (Make Executable Readable)
-        // SIE (Supervisor Interrupt Enable): enable S-mode interrupt
         let mut current_sstatus = sstatus::read();
         current_sstatus.set_spp(sstatus::SPP::Supervisor);
         current_sstatus.set_sum(true);
         current_sstatus.set_mxr(true);
-        current_sstatus.set_sie(true);
         sstatus::write(current_sstatus);
-
-        // setup kernel page table and flush tlb
-        setup_kernel_satp();
     }
 
     /// Boot all other hart.
     pub unsafe fn bootstrap_cpus(&self) {
-        unsafe extern "C" {
-        fn ap_boot_entry();
-        }
-        let total_harts = get_num_harts();
-
-        let ap_entry_point = PhysicalAddress::new(ap_boot_entry as usize);
-
-        for i in 0..total_harts {
-            if i == self.hart_id {
-                continue;
-            }
-            sbi::hsm::hart_start(i, ap_entry_point, 0)
+        let total_harts = FDT.hart_count();
+        for i in (0..total_harts).filter(|&i| i != self.hart_id) {
+            sbi::hsm::hart_start(i, todo!("AP entry"), 0)
                 .expect("Failed to start secondary hart via SBI");
         }
     }
@@ -107,11 +75,7 @@ impl CPU {
     }
 
     pub fn end_of_interrupt(self: Pin<&mut Self>) {
-        unsafe {
-            // TODO: 不知道写的对不对。。。
-            self.map_unchecked_mut(|me| &mut me.interrupt)
-                .clear_soft_interrupt_pending();
-        }
+        todo!()
     }
 
     pub fn local() -> PreemptGuard<Pin<&'static mut Self>> {
@@ -126,65 +90,3 @@ impl CPU {
         self.hart_id
     }
 }
-
-#[macro_export]
-macro_rules! define_smp_bootstrap {
-    ($cpu_count:literal, $ap_entry:ident, $alloc_kstack:tt) => {
-        #[no_mangle]
-        static BOOT_SEMAPHORE: core::sync::atomic::AtomicU64 =
-            core::sync::atomic::AtomicU64::new(0);
-        #[no_mangle]
-        static BOOT_STACK: core::sync::atomic::AtomicU64 =
-            core::sync::atomic::AtomicU64::new(0);
-
-        #[no_mangle]
-        static CPU_COUNT: core::sync::atomic::AtomicU64 =
-            core::sync::atomic::AtomicU64::new(0);
-
-        core::arch::global_asm!(
-            r#"
-        .section .text.ap_boot
-        .globl ap_boot_entry
-
-        ap_boot_entry:
-            csrr a0, mhartid
-
-        1:
-            lw t0, AP_BOOT_STACK.addr
-            beqz t0, 1b
-            li t1, 0
-            sw t1, AP_BOOT_STACK.addr
-            mv sp, t0
-
-        2:
-            lw t0, AP_BOOT_SEMAPHORE.addr
-            beqz t0, 2b
-
-            li t1, 0
-            sw t1, AP_BOOT_SEMAPHORE.addr
-
-            li t0, 1
-            amoswap.w.aq rl t0, a0, ONLINE_HART_COUNT.addr
-
-            call $ap_entry
-            j .
-            "#,
-            BOOT_SEMAPHORE = sym BOOT_SEMAPHORE,
-            BOOT_STACK = sym BOOT_STACK,
-            CPU_COUNT = sym CPU_COUNT,
-            AP_ENTRY = sym $ap_entry,
-        );
-
-        pub unsafe fn wait_cpus_online() {
-            use core::sync::atomic::Ordering;
-            while CPU_COUNT.load(Ordering::Acquire) != $cpu_count - 1 {
-                if BOOT_STACK.load(Ordering::Acquire) == 0 {
-                    let stack_bottom = $alloc_kstack as u64;
-                    BOOT_STACK.store(stack_bottom, Ordering::Release);
-                }
-                $crate::pause();
-            }
-        }
-    };
-}
-

+ 51 - 29
crates/eonix_hal/src/arch/riscv64/fdt.rs

@@ -1,40 +1,62 @@
-extern crate alloc;
-
-use alloc::string::String;
-
+use super::mm::{ArchPhysAccess, PresentRam};
+use crate::arch::riscv64::config::mm::KIMAGE_OFFSET;
+use core::sync::atomic::{AtomicPtr, Ordering};
+use eonix_mm::address::{PAddr, PRange, PhysAccess};
+use eonix_sync_base::LazyLock;
 use fdt::Fdt;
-use spin::Once;
 
-use crate::arch::riscv64::config::mm::KIMAGE_OFFSET;
+static DTB_VIRT_PTR: AtomicPtr<u8> = AtomicPtr::new(core::ptr::null_mut());
+pub static FDT: LazyLock<Fdt<'static>> = LazyLock::new(|| unsafe {
+    Fdt::from_ptr(DTB_VIRT_PTR.load(Ordering::Acquire))
+        .expect("Failed to parse DTB from static memory.")
+});
 
-static GLOBAL_FDT: Once<Fdt<'static>> = Once::new();
+pub trait FdtExt {
+    fn harts(&self) -> impl Iterator<Item = usize>;
 
-pub unsafe fn init_dtb_and_fdt(dtb_pa: usize) {
-    let dtb_virt_ptr = (dtb_pa + KIMAGE_OFFSET) as *const u8;
+    fn hart_count(&self) -> usize {
+        self.harts().count()
+    }
 
-    GLOBAL_FDT.call_once(|| {
-        unsafe { Fdt::from_ptr(dtb_virt_ptr)
-            .expect("Failed to parse DTB from static memory.") }
-    });
+    fn present_ram(&self) -> impl Iterator<Item = PRange>;
 }
 
-pub fn get_global_fdt() -> &'static Fdt<'static> {
-    GLOBAL_FDT.get().expect("Global FDT has not been initialized yet")
-}
+impl FdtExt for Fdt<'_> {
+    fn harts(&self) -> impl Iterator<Item = usize> {
+        self.cpus().map(|cpu| cpu.ids().all()).flatten()
+    }
 
-#[derive(Debug, Clone)]
-pub struct HartInfo {
-    pub hart_id: usize,
-    pub compatible: Option<String>,
+    fn present_ram(&self) -> impl Iterator<Item = PRange> + PresentRam {
+        struct Present<I>(I);
+        impl<I> PresentRam for Present<I> where I: Iterator<Item = PRange> {}
+        impl<I> Iterator for Present<I>
+        where
+            I: Iterator<Item = PRange>,
+        {
+            type Item = PRange;
+
+            fn next(&mut self) -> Option<Self::Item> {
+                self.0.next()
+            }
+        }
+
+        let mut index = 0;
+        Present(core::iter::from_fn(move || {
+            self.memory()
+                .regions()
+                .filter_map(|region| {
+                    region.size.map(|len| {
+                        PRange::from(PAddr::from(region.starting_address as usize)).grow(len)
+                    })
+                })
+                .skip(index)
+                .next()
+                .inspect(|_| index += 1)
+        }))
+    }
 }
 
-pub fn get_num_harts() -> usize {
-    let fdt = get_global_fdt();
-    let dtb_cpus = fdt.cpus();
-    let mut num_harts = 0;
-
-    for _cpu in dtb_cpus {
-        num_harts += 1;
-    }
-    num_harts
+pub unsafe fn init_dtb_and_fdt(dtb_paddr: PAddr) {
+    let dtb_virt_ptr = ArchPhysAccess::as_ptr(dtb_paddr);
+    DTB_VIRT_PTR.store(dtb_virt_ptr.as_ptr(), Ordering::Release);
 }

+ 0 - 62
crates/eonix_hal/src/arch/riscv64/interrupt/clint.rs

@@ -1,62 +0,0 @@
-use super::super::config::platform::virt::*;
-use core::ptr;
-
-use sbi::{
-    ipi::send_ipi,
-    timer::set_timer,
-    HartMask,
-    SbiError
-};
-use riscv::register::mie;
-
-/// CLINT (Core Local Interruptor) driver
-/// This struct now owns the base address and hart_id.
-pub struct ClintDriver {
-    base_addr: usize,
-    hart_id: usize,
-}
-
-impl ClintDriver {
-    pub fn new(base_addr: usize, hart_id: usize) -> Self {
-        let driver = ClintDriver { base_addr, hart_id };
-
-        driver.clear_soft_interrupt_pending(hart_id);
-
-        // Enable Supervisor-mode Software Interrupts (SSIE)
-        // and Supervisor-mode Timer Interrupts (STIE) in the `mie` CSR.
-        unsafe {
-            mie::set_ssoft(); // Enable S-mode Software Interrupts
-            mie::set_stimer(); // Enable S-mode Timer Interrupts
-        }
-
-        driver
-    }
-
-    /// Reads the current value of the global MTIME (Machine Timer) counter.
-    pub fn get_time(&self) -> u64 {
-        unsafe {
-            // MTIME is a 64-bit counter at CLINT_BASE + CLINT_MTIME_OFFSET
-            ptr::read_volatile((self.base_addr + CLINT_MTIME_OFFSET) as *mut u64)
-        }
-    }
-
-    /// Sets the next timer interrupt trigger point using SBI.
-    pub fn set_timer(&self, time_value: u64) -> Result<(), SbiError> {
-        set_timer(time_value)
-    }
-
-    /// Sends an Inter-Processor Interrupt (IPI) to the specified Hart(s).
-    pub fn send_ipi(&self, hart_id_mask: usize) -> Result<(), SbiError> {
-        // This utilizes the SBI `send_ipi` call.
-        send_ipi(HartMask::from(hart_id_mask))
-    }
-
-    /// Clears the software interrupt pending bit for the specified Hart.
-    pub fn clear_soft_interrupt_pending(&self, hart_id: usize) {
-        unsafe {
-            // MSIP registers are typically located at CLINT_BASE + 4 * hart_id.
-            // Writing 0 to the register clears the pending bit.
-            ptr::write_volatile((self.base_addr + CLINT_MSIP_OFFSET + hart_id * 4) as *mut u32, 0);
-        }
-    }
-}

+ 24 - 63
crates/eonix_hal/src/arch/riscv64/interrupt/mod.rs

@@ -1,79 +1,40 @@
-mod plic;
-mod clint;
-
-use plic::*;
-use clint::*;
+use core::pin::Pin;
 
+use super::config::platform::virt::*;
+use riscv_peripheral::{
+    aclint::{Clint, CLINT},
+    plic::{Plic, PLIC},
+};
 use sbi::SbiError;
 
-use super::config::platform::virt::*;
+#[derive(Clone, Copy)]
+struct ArchPlic;
+
+#[derive(Clone, Copy)]
+struct ArchClint;
+
+unsafe impl Plic for ArchPlic {
+    const BASE: usize = PLIC_BASE;
+}
+
+unsafe impl Clint for ArchClint {
+    const BASE: usize = CLINT_BASE;
+    const MTIME_FREQ: usize = CPU_FREQ_HZ as usize;
+}
 
 /// Architecture-specific interrupt control block.
 pub struct InterruptControl {
-    hart_id: usize,
-    plic: PlicDriver,
-    clint: ClintDriver,
+    clint: CLINT<ArchClint>,
 }
 
 impl InterruptControl {
     /// # Safety
     /// should be called only once.
-    pub(crate) fn new(hart_id: usize) -> Self {
-        // Initialize PLICDriver for this Hart
-        let plic = PlicDriver::new(PLIC_BASE, hart_id);
-
-        // Initialize ClintDriver for this Hart
-        let clint = ClintDriver::new(CLINT_BASE, hart_id);
-
+    pub(crate) fn new() -> Self {
         Self {
-            hart_id,
-            plic: plic,
-            clint: clint,
-        }
-    }
-
-    /// Configures the CLINT timer for a periodic interrupt.
-    ///
-    /// # Arguments
-    /// * `interval_us`: The desired interval between timer interrupts in microseconds.
-    pub fn setup_timer(&self, interval_us: u64) {
-        let current_time = self.clint.get_time();
-        // Calculate ticks per microsecond based on CPU_FREQ_HZ
-        let ticks_per_us = CPU_FREQ_HZ / 1_000_000;
-        let ticks = interval_us * ticks_per_us;
-
-        let next_timer_at = current_time.checked_add(ticks).unwrap_or(u64::MAX);
-
-        if let Err(e) = self.clint.set_timer(next_timer_at) {
-            panic!("Failed to set CLINT timer: {:?}", e);
+            clint: CLINT::new(),
         }
     }
 
-    /// Sends an Inter-Processor Interrupt (IPI) to target Harts.
-    pub fn send_ipi(&self, target_hart_mask: usize) -> Result<(), SbiError> {
-        self.clint.send_ipi(target_hart_mask)
-    }
-
-    /// Handles the "End Of Interrupt" (EOI) for the most recently claimed
-    /// external interrupt.
-    pub fn end_of_external_interrupt(&self, irq_id: u32) {
-        self.plic.complete_interrupt(irq_id);
-    }
-
-    /// Clears the pending software interrupt for the current Hart.
-    pub fn clear_soft_interrupt_pending(&self) {
-        self.clint.clear_soft_interrupt_pending(self.hart_id);
-    }
-
-    pub fn plic_enable_interrupt(&self, irq_id: u32) {
-        self.plic.enable_interrupt(irq_id);
-    }
-
-    pub fn plic_set_priority(&self, irq_id: u32, priority: u32) {
-        self.plic.set_priority(irq_id, priority);
-    }
-
-    pub fn plic_claim_interrupt(&self) -> u32 {
-        self.plic.claim_interrupt()
-    }
+    pub fn init(self: Pin<&mut Self>) {}
 }

+ 0 - 137
crates/eonix_hal/src/arch/riscv64/interrupt/plic.rs

@@ -1,137 +0,0 @@
-use core::ptr::{read_volatile, write_volatile};
-
-use super::super::config::platform::virt::*;
-
-use riscv::register::mie;
-
-pub struct PlicDriver {
-    base_addr: usize,
-    hart_id: usize,
-}
-
-impl PlicDriver {
-    pub fn new(base_addr: usize, hart_id: usize) -> Self {
-        let driver = PlicDriver { base_addr, hart_id };
-
-        let s_context_id = driver.s_context_id();
-
-        driver.set_priority_threshold(0);
-
-        let enable_reg_base_for_context = driver.enable_addr(s_context_id);
-        // PLIC enable bits are grouped into 32-bit registers.
-        // Assuming 32 registers for up to 1024 IRQs, but 32 is common for a few hundred.
-        for i in 0..(driver.max_irq_num() / 32 + 1) {
-            let reg_addr = (enable_reg_base_for_context as usize + (i as usize) * 4) as *mut u32;
-            unsafe {
-                (reg_addr as *mut u32).write_volatile(0);
-            }
-        }
-
-        unsafe {
-            mie::set_sext();
-        }
-
-        driver.set_priority(10, 1);
-        driver.enable_interrupt(10);
-
-        // TODO: may need more set_priority
-        // driver.set_priority(UART_IRQ_ID, 1);
-        // driver.enable_interrupt(UART_IRQ_ID);
-        // driver.set_priority(VIRTIO_BLOCK_IRQ_ID, 1);
-        // driver.enable_interrupt(VIRTIO_BLOCK_IRQ_ID);
-
-        driver
-    }
-
-    fn s_context_id(&self) -> usize {
-        self.hart_id * PLIC_S_MODE_CONTEXT_STRIDE + 1
-    }
-
-    fn priority_addr(&self, irq_id: u32) -> *mut u32 {
-        (self.base_addr + PLIC_PRIORITY_OFFSET + (irq_id as usize) * 4) as *mut u32
-    }
-
-    fn pending_addr(&self) -> *mut u32 {
-        (self.base_addr + PLIC_PENDING_OFFSET) as *mut u32
-    }
-
-    fn enable_addr(&self, context_id: usize) -> *mut u32 {
-        // PLIC enable bits are typically organized as 32-bit banks.
-        // The offset for each context's enable registers.
-        // A common stride for context enable blocks is 0x80 (128 bytes).
-        (self.base_addr + PLIC_ENABLE_OFFSET + context_id * PLIC_ENABLE_PER_HART_OFFSET) as *mut u32
-    }
-
-    fn threshold_addr(&self, context_id: usize) -> *mut u32 {
-        // A common stride for context threshold/claim/complete registers is 0x1000 (4KB).
-        (self.base_addr + PLIC_THRESHOLD_OFFSET + context_id * PLIC_THRESHOLD_CLAIM_COMPLETE_PER_HART_OFFSET) as *mut u32
-    }
-
-    fn claim_complete_addr(&self, context_id: usize) -> *mut u32 {
-        (self.base_addr + PLIC_CLAIM_COMPLETE_OFFSET + context_id * PLIC_THRESHOLD_CLAIM_COMPLETE_PER_HART_OFFSET) as *mut u32
-    }
-
-    pub fn set_priority(&self, irq_id: u32, priority: u32) {
-        unsafe {
-            write_volatile(self.priority_addr(irq_id), priority);
-        }
-    }
-
-    pub fn get_priority(&self, irq_id: u32) -> u32 {
-        unsafe { read_volatile(self.priority_addr(irq_id)) }
-    }
-
-    pub fn enable_interrupt(&self, irq_id: u32) {
-        let context_id = self.s_context_id();
-        let enable_reg_offset_in_bank = (irq_id / 32) as usize * 4;
-        let bit_index_in_reg = irq_id % 32;
-
-        let enable_reg_addr = (self.enable_addr(context_id) as usize + enable_reg_offset_in_bank) as *mut u32;
-        let bit_mask = 1 << bit_index_in_reg;
-        unsafe {
-            let old = read_volatile(enable_reg_addr);
-            write_volatile(enable_reg_addr, old | bit_mask);
-        }
-    }
-
-    pub fn disable_interrupt(&self, irq_id: u32) {
-        let context_id = self.s_context_id();
-        let enable_reg_offset_in_bank = (irq_id / 32) as usize * 4;
-        let bit_index_in_reg = irq_id % 32;
-
-        let enable_reg_addr = (self.enable_addr(context_id) as usize + enable_reg_offset_in_bank) as *mut u32;
-        let bit_mask = 1 << bit_index_in_reg;
-        unsafe {
-            let old = read_volatile(enable_reg_addr);
-            write_volatile(enable_reg_addr, old & !bit_mask);
-        }
-    }
-
-    pub fn set_priority_threshold(&self, threshold: u32) {
-        let context_id = self.s_context_id();
-        unsafe {
-            write_volatile(self.threshold_addr(context_id), threshold);
-        }
-    }
-
-    pub fn get_priority_threshold(&self) -> u32 {
-        let context_id = self.s_context_id();
-        unsafe { read_volatile(self.threshold_addr(context_id)) }
-    }
-
-    pub fn claim_interrupt(&self) -> u32 {
-        let context_id = self.s_context_id();
-        unsafe { read_volatile(self.claim_complete_addr(context_id)) }
-    }
-
-    pub fn complete_interrupt(&self, irq_id: u32) {
-        let context_id = self.s_context_id();
-        unsafe {
-            write_volatile(self.claim_complete_addr(context_id), irq_id);
-        }
-    }
-
-    pub fn max_irq_num(&self) -> u32 {
-        127
-    }
-}

+ 21 - 16
crates/eonix_hal/src/arch/riscv64/link.x

@@ -1,10 +1,25 @@
+SECTIONS {
+    .bootstrap ORIGIN(RAM) :
+    {
+        KEEP(*(.bootstrap.entry .bootstrap.data));
+
+        . = ORIGIN(RAM) + 0x1000;
+        KEEP(*(.bootstrap.page_table.1));
+        KEEP(*(.bootstrap.page_table.2));
+
+        . = ALIGN(16);
+        KEEP(*(.bootstrap.stack));
+    } > RAM
+}
+INSERT BEFORE .text;
+
 SECTIONS {
     .text.syscall_fns :
     {
 
         KEEP(*(.syscall_fns*));
 
-    } > REGION_TEXT
+    } > REGION_TEXT AT> RAM
 }
 INSERT AFTER .text;
 
@@ -17,7 +32,7 @@ SECTIONS {
         KEEP(*(.fix));
 
         FIX_END = .;
-    } > REGION_RODATA
+    } > REGION_RODATA AT> RAM
 
     .rodata.syscalls :
     {
@@ -31,16 +46,16 @@ SECTIONS {
 
         RAW_SYSCALL_HANDLERS_SIZE =
             ABSOLUTE(__raw_syscall_handlers_end - __raw_syscall_handlers_start);
-    } > REGION_RODATA
+    } > REGION_RODATA AT> RAM
 }
 INSERT AFTER .rodata;
 
 SECTIONS {
-    .percpu 0 : ALIGN(16)
+    .percpu : ALIGN(16)
     {
         __spercpu = .;
 
-        PERCPU_START = .;
+        PERCPU_DATA_START = .;
 
         . = ALIGN(16);
 
@@ -48,9 +63,8 @@ SECTIONS {
 
         . = ALIGN(16);
         __epercpu = .;
-    } > LOWMEM AT> REGION_RODATA
+    } > REGION_RODATA AT> RAM
 
-    PERCPU_DATA_START = LOADADDR(.percpu);
     PERCPU_LENGTH = ABSOLUTE(__epercpu - __spercpu);
 
     KIMAGE_PAGES = (__edata - _stext + 0x1000 - 1) / 0x1000;
@@ -60,12 +74,3 @@ SECTIONS {
     BSS_LENGTH = ABSOLUTE(__ebss - __sbss);
 }
 INSERT AFTER .rodata;
-
-SECTIONS {
-    .bootregion : {
-        . = ALIGN(4096);
-        *(.bootstack);
-        *(.bootdata);
-    } > REGION_BOOT
-}
-INSERT AFTER .rodata;

+ 3 - 4
crates/eonix_hal/src/arch/riscv64/memory.x

@@ -1,17 +1,16 @@
 OUTPUT_ARCH(riscv)
 ENTRY(_start)
 
-RAM = 0x80200000;
-
 MEMORY {
-    LOWMEM : org = 0x0000000000000000, len = 1M
+    RAM    : org = 0x0000000080200000, len = 4M
     KBSS   : org = 0xffffffff40000000, len = 2M
     KIMAGE : org = 0xffffffff80200000, len = 2M
 }
 
 REGION_ALIAS("REGION_TEXT", KIMAGE);
 REGION_ALIAS("REGION_RODATA", KIMAGE);
-REGION_ALIAS("REGION_BOOT", KIMAGE);
 REGION_ALIAS("REGION_DATA", KIMAGE);
 REGION_ALIAS("REGION_BSS", KBSS);
 REGION_ALIAS("REGION_EHFRAME", KIMAGE);
+
+_stext = ORIGIN(REGION_TEXT) + LOADADDR(.text) - ORIGIN(RAM);

+ 57 - 55
crates/eonix_hal/src/arch/riscv64/mm.rs

@@ -1,25 +1,21 @@
-extern crate alloc;
-
-
-use crate::{arch::{fdt::get_global_fdt, riscv64::config::mm::KIMAGE_OFFSET}, traits::mm::Memory};
+use super::{
+    config::mm::{PHYS_MAP_VIRT, ROOT_PAGE_TABLE_PFN},
+    fdt::{FdtExt, FDT},
+};
+use crate::{arch::riscv64::config::mm::KIMAGE_OFFSET, traits::mm::Memory};
 use core::{marker::PhantomData, ptr::NonNull};
 use eonix_mm::{
-    address::{Addr as _, AddrOps, PAddr, PRange, PhysAccess, VAddr}, page_table::{
-        PageAttribute, PageTable, PageTableLevel, PagingMode, RawAttribute, RawPageTable, TableAttribute, PTE
-    }, paging::{NoAlloc, Page, PageBlock, PFN}
+    address::{Addr as _, AddrOps, PAddr, PRange, PhysAccess, VAddr},
+    page_table::{
+        PageAttribute, PageTable, PageTableLevel, PagingMode, RawAttribute, RawPageTable,
+        TableAttribute, PTE,
+    },
+    paging::{NoAlloc, Page, PageBlock, PFN},
 };
 use eonix_sync_base::LazyLock;
 use fdt::Fdt;
 use riscv::{asm::sfence_vma_all, register::satp};
 
-use super::config::mm::{
-    ROOT_PAGE_TABLE_PFN,
-    PHYS_MAP_VIRT
-};
-
-pub const P_KIMAGE_START: PAddr = PAddr::from_val(0x80200000);
-pub const V_KERNEL_BSS_START: VAddr = VAddr::from(0xffffffff00000000);
-
 pub const PAGE_TABLE_BASE: PFN = PFN::from_val(ROOT_PAGE_TABLE_PFN);
 pub static GLOBAL_PAGE_TABLE: LazyLock<PageTable<ArchPagingMode, NoAlloc, ArchPhysAccess>> =
     LazyLock::new(|| unsafe {
@@ -54,9 +50,9 @@ pub struct PTE64(pub u64);
 #[derive(Clone, Copy)]
 pub struct PageAttribute64(u64);
 
-pub struct RawPageTableSv39<'a>(NonNull<PTE64>, PhantomData<&'a ()>);
+pub struct RawPageTableSv48<'a>(NonNull<PTE64>, PhantomData<&'a ()>);
 
-pub struct PagingModeSv39;
+pub struct PagingModeSv48;
 
 pub struct ArchPhysAccess;
 
@@ -76,19 +72,20 @@ impl PTE for PTE64 {
     }
 }
 
-impl PagingMode for PagingModeSv39 {
+impl PagingMode for PagingModeSv48 {
     type Entry = PTE64;
-    type RawTable<'a> = RawPageTableSv39<'a>;
+    type RawTable<'a> = RawPageTableSv48<'a>;
     const LEVELS: &'static [PageTableLevel] = &[
+        PageTableLevel::new(39, 9),
         PageTableLevel::new(30, 9),
         PageTableLevel::new(21, 9),
         PageTableLevel::new(12, 9),
     ];
 }
 
-pub type ArchPagingMode = PagingModeSv39;
+pub type ArchPagingMode = PagingModeSv48;
 
-impl<'a> RawPageTable<'a> for RawPageTableSv39<'a> {
+impl<'a> RawPageTable<'a> for RawPageTableSv48<'a> {
     type Entry = PTE64;
 
     fn index(&self, index: u16) -> &'a Self::Entry {
@@ -203,7 +200,7 @@ impl From<PageAttribute> for PageAttribute64 {
                 PageAttribute::GLOBAL => raw_attr |= PA_G,
                 PageAttribute::COPY_ON_WRITE => raw_attr |= PA_COW,
                 PageAttribute::MAPPED => raw_attr |= PA_MMAP,
-                PageAttribute::ANONYMOUS => {},
+                PageAttribute::ANONYMOUS => {}
                 _ => unreachable!("Invalid page attribute"),
             }
         }
@@ -260,41 +257,20 @@ impl PhysAccess for ArchPhysAccess {
 }
 
 impl Memory for ArchMemory {
-    /// TODO: fuck, I don't know how to fix
-    fn present_ram() -> impl Iterator<Item = eonix_mm::address::PRange> {
-        let fdt: &'static Fdt<'static> = get_global_fdt();
-
-        let memory_node = fdt.memory().clone();
-
-        let owned_ranges: alloc::vec::Vec<PRange> = memory_node.regions() 
-            .map(|mem_region| {
-                let base = mem_region.starting_address as usize;
-                let size = mem_region.size.expect("this region has no memory") as usize;
-                PRange::from(PAddr::from(base as usize)).grow(size as usize)
-            }).collect();
-        
-        owned_ranges.into_iter()
+    fn present_ram() -> impl Iterator<Item = PRange> {
+        FDT.present_ram()
     }
 
-    fn free_ram() -> impl Iterator<Item = eonix_mm::address::PRange> {
+    fn free_ram() -> impl Iterator<Item = PRange> {
         unsafe extern "C" {
             fn __kernel_start();
             fn __kernel_end();
         }
 
         let kernel_end = PAddr::from(__kernel_end as usize - KIMAGE_OFFSET);
-        let paddr_after_kimage_aligned = kernel_end.ceil_to(0x2000000);
-
-        core::iter::once(PRange::new(
-            kernel_end,
-            paddr_after_kimage_aligned,
-        ))
-
-        /*core::iter::once(PRange::new(
-            kernel_end,
-            paddr_after_kimage_aligned,
-        ))
-        .chain(
+        let paddr_after_kimage_aligned = kernel_end.ceil_to(0x200000);
+
+        core::iter::once(PRange::new(kernel_end, paddr_after_kimage_aligned)).chain(
             Self::present_ram()
                 .filter(move |range| range.end() > paddr_after_kimage_aligned)
                 .map(move |range| {
@@ -305,15 +281,41 @@ impl Memory for ArchMemory {
                         range
                     }
                 }),
-        )*/
+        )
     }
 }
 
-pub type DefaultPagingMode = PagingModeSv39;
+pub type DefaultPagingMode = PagingModeSv48;
 
-pub fn setup_kernel_satp() {
-    unsafe {
-        satp::set(satp::Mode::Sv39, 0, PFN::from(ROOT_PAGE_TABLE_PFN).into());
+pub trait PresentRam: Iterator<Item = PRange> {}
+
+pub trait FreeRam: PresentRam {
+    fn free_ram(self) -> impl Iterator<Item = PRange>;
+}
+
+impl<T> FreeRam for T
+where
+    T: PresentRam,
+{
+    fn free_ram(self) -> impl Iterator<Item = PRange> {
+        unsafe extern "C" {
+            fn __kernel_start();
+            fn __kernel_end();
+        }
+
+        let kernel_end = PAddr::from(__kernel_end as usize - KIMAGE_OFFSET);
+        let paddr_after_kimage_aligned = kernel_end.ceil_to(0x200000);
+
+        core::iter::once(PRange::new(kernel_end, paddr_after_kimage_aligned)).chain(
+            self.filter(move |range| range.end() > paddr_after_kimage_aligned)
+                .map(move |range| {
+                    if range.start() < paddr_after_kimage_aligned {
+                        let (_, right) = range.split_at(paddr_after_kimage_aligned);
+                        right
+                    } else {
+                        range
+                    }
+                }),
+        )
     }
-    sfence_vma_all();
 }

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

@@ -1,12 +1,9 @@
 pub mod bootstrap;
+mod config;
+pub mod console;
+pub mod context;
 pub mod cpu;
 pub mod fdt;
+pub mod interrupt;
 pub mod mm;
-pub mod context;
 pub mod trap;
-pub mod interrupt;
-pub mod console;
-mod config;
-
-// TODO:
-// linker

+ 37 - 42
crates/eonix_hal/src/arch/riscv64/trap/mod.rs

@@ -1,28 +1,22 @@
 mod trap_context;
 
+use super::config::platform::virt::*;
+use super::context::TaskContext;
+use core::arch::{global_asm, naked_asm};
 use eonix_hal_traits::{context::RawTaskContext, trap::TrapReturn};
-pub use trap_context::*;
-
+use riscv::register::sie::Sie;
+use riscv::register::stvec::TrapMode;
+use riscv::register::{scause, sepc, stval};
 use riscv::{
     asm::sfence_vma_all,
     register::{
-        sstatus::{self, Sstatus},
-        stvec::{self, Stvec}
-    }
+        sie,
+        stvec::{self, Stvec},
+    },
 };
 use sbi::SbiError;
-use core::arch::{global_asm, naked_asm};
 
-use super::context::TaskContext;
-
-use super::config::platform::virt::*;
-
-//global_asm!(include_str!("trap.S"));
-
-use riscv::register::{scause, sepc, stval};
-
-//#[eonix_percpu::define_percpu]
-//static TRAP_HANDLER: unsafe extern "C" fn() = default_trap_handler;
+pub use trap_context::*;
 
 #[eonix_percpu::define_percpu]
 static TRAP_HANDLER: unsafe extern "C" fn() = default_trap_handler;
@@ -33,6 +27,14 @@ static CAPTURER_CONTEXT: TaskContext = TaskContext::new();
 /// This value will never be used.
 static mut DIRTY_TRAP_CONTEXT: TaskContext = TaskContext::new();
 
+#[unsafe(naked)]
+unsafe extern "C" fn _raw_trap_entry() -> ! {
+    naked_asm!(
+        "j {entry}",
+        entry = sym _raw_trap_entry,
+    );
+}
+
 // TODO: is need to save kernel's callee saved registers?
 global_asm!(
     r"
@@ -45,11 +47,11 @@ global_asm!(
     .endm
 
     .section .text
-        .globl _raw_trap_entry
+        .globl __raw_trap_entry
         .globl return_to_user
         .align 2
 
-    _raw_trap_entry:
+    __raw_trap_entry:
         # swap sp and sscratch(previously stored user TrapContext's address in return_to_user)
         csrrw sp, sscratch, sp
 
@@ -110,7 +112,6 @@ global_asm!(
 
 unsafe extern "C" {
     fn _default_trap_handler(trap_context: &mut TrapContext);
-    fn _raw_trap_entry();
     fn _raw_trap_return();
 }
 
@@ -189,10 +190,13 @@ impl TrapReturn for TrapContext {
 }
 
 fn setup_trap_handler(trap_entry_addr: usize) {
+    let mut stvec_val = Stvec::from_bits(0);
+    stvec_val.set_address(trap_entry_addr);
+    stvec_val.set_trap_mode(TrapMode::Direct);
+
     unsafe {
-        stvec::write(Stvec::from_bits(trap_entry_addr));
+        stvec::write(stvec_val);
     }
-    sfence_vma_all();
 }
 
 pub fn setup_trap() {
@@ -200,54 +204,45 @@ pub fn setup_trap() {
 }
 
 #[derive(Debug, Clone, Copy, PartialEq, Eq)]
-pub struct IrqState(usize);
+pub struct IrqState(Sie);
 
 impl IrqState {
     #[inline]
     pub fn save() -> Self {
-        let sstatus_val = sstatus::read().bits();
-
-        unsafe {
-            sstatus::clear_sie();
-        }
-
-        IrqState(sstatus_val)
+        IrqState(sie::read())
     }
 
     #[inline]
     pub fn restore(self) {
         let Self(state) = self;
         unsafe {
-            sstatus::write(Sstatus::from_bits(state));
+            sie::write(state);
         }
     }
-
-    #[inline]
-    pub fn was_enabled(&self) -> bool {
-        (self.0 & (1 << 1)) != 0
-    }
 }
 
 #[inline]
 pub fn disable_irqs() {
     unsafe {
-        sstatus::clear_sie();
+        sie::clear_sext();
+        sie::clear_stimer();
+        sie::clear_ssoft();
     }
 }
 
 #[inline]
 pub fn enable_irqs() {
     unsafe {
-        sstatus::set_sie();
+        sie::set_sext();
+        sie::set_stimer();
+        sie::set_ssoft();
     }
 }
 
 #[inline]
 pub fn disable_irqs_save() -> IrqState {
-    unsafe {
-        let original_sstatus_bits = sstatus::read().bits();
-        sstatus::clear_sie();
+    let state = IrqState::save();
+    disable_irqs();
 
-        IrqState(original_sstatus_bits)
-    }
+    state
 }

+ 34 - 51
crates/eonix_hal/src/arch/riscv64/trap/trap_context.rs

@@ -1,9 +1,17 @@
 use core::arch::asm;
-use eonix_hal_traits::{fault::{Fault, PageFaultErrorCode}, trap::{RawTrapContext, TrapType}};
+use eonix_hal_traits::{
+    fault::{Fault, PageFaultErrorCode},
+    trap::{RawTrapContext, TrapType},
+};
 use riscv::{
-    interrupt::{Exception, Interrupt, Trap}, register::{
-        scause, sie, sstatus::{self, Sstatus, SPP}, stval
-    }, ExceptionNumber, InterruptNumber
+    interrupt::{Exception, Interrupt, Trap},
+    register::{
+        scause::{self, Scause},
+        sie,
+        sstatus::{self, Sstatus, SPP},
+        stval,
+    },
+    ExceptionNumber, InterruptNumber,
 };
 
 /// Floating-point registers context.
@@ -22,15 +30,8 @@ pub struct TrapContext {
 
     // CSRs
     pub sstatus: Sstatus, // sstatus CSR value. Contains privilege mode, interrupt enable, FPU state.
-    pub sepc: usize,    // sepc (Supervisor Exception Program Counter). Program counter at trap.
-    pub scause: usize,  // S-mode Trap Cause Register
-    pub stval: usize,
-    
-    //pub kernel_sp: usize,
-    //pub kernel_ra: usize,
-    //pub kernel_s: [usize; 12],
-    //pub kernel_fp: usize,
-    //pub kernel_tp: usize,
+    pub sepc: usize,      // sepc (Supervisor Exception Program Counter). Program counter at trap.
+    pub scause: Scause,   // S-mode Trap Cause Register
 }
 
 impl TrapContext {
@@ -40,12 +41,7 @@ impl TrapContext {
 
     fn syscall_args(&self) -> [usize; 6] {
         [
-            self.x[10],
-            self.x[11],
-            self.x[12],
-            self.x[13],
-            self.x[14],
-            self.x[15],
+            self.x[10], self.x[11], self.x[12], self.x[13], self.x[14], self.x[15],
         ]
     }
 }
@@ -57,19 +53,12 @@ impl RawTrapContext for TrapContext {
             x: [0; 32],
             sstatus: sstatus::read(),
             sepc: 0,
-            scause: 0,
-            stval: 0,
-            //kernel_sp: 0,
-            //kernel_ra: 0,
-            //kernel_s: [0; 12],
-            //kernel_fp: 0,
-            //kernel_tp: 0
+            scause: Scause::from_bits(0),
         }
     }
 
     fn trap_type(&self) -> TrapType {
-        let scause = scause::Scause::from_bits(self.scause);
-        let cause = scause.cause();
+        let cause = self.scause.cause();
         match cause {
             Trap::Interrupt(i) => {
                 match Interrupt::from_number(i).unwrap() {
@@ -82,33 +71,27 @@ impl RawTrapContext for TrapContext {
             }
             Trap::Exception(e) => {
                 match Exception::from_number(e).unwrap() {
-                    Exception::InstructionMisaligned |
-                    Exception::LoadMisaligned |
-                    Exception::InstructionFault |
-                    Exception::LoadFault |
-                    Exception::StoreFault |
-                    Exception::StoreMisaligned => {
-                        TrapType::Fault(Fault::BadAccess)
-                    },
-                    Exception::IllegalInstruction => {
-                        TrapType::Fault(Fault::InvalidOp)
-                    }
-                    Exception::UserEnvCall => {
-                        TrapType::Syscall { 
-                            no: self.syscall_no(),
-                            args: self.syscall_args()
-                        }
+                    Exception::InstructionMisaligned
+                    | Exception::LoadMisaligned
+                    | Exception::InstructionFault
+                    | Exception::LoadFault
+                    | Exception::StoreFault
+                    | Exception::StoreMisaligned => TrapType::Fault(Fault::BadAccess),
+                    Exception::IllegalInstruction => TrapType::Fault(Fault::InvalidOp),
+                    Exception::UserEnvCall => TrapType::Syscall {
+                        no: self.syscall_no(),
+                        args: self.syscall_args(),
                     },
-                    Exception::InstructionPageFault |
-                    Exception::LoadPageFault |
-                    Exception::StorePageFault => {
+                    Exception::InstructionPageFault
+                    | Exception::LoadPageFault
+                    | Exception::StorePageFault => {
                         let e = Exception::from_number(e).unwrap();
                         TrapType::Fault(Fault::PageFault(self.get_page_fault_error_code(e)))
-                    },
+                    }
                     // breakpoint and supervisor env call
                     _ => TrapType::Fault(Fault::Unknown(e)),
                 }
-            },
+            }
         }
     }
 
@@ -136,14 +119,14 @@ impl RawTrapContext for TrapContext {
     fn set_interrupt_enabled(&mut self, enabled: bool) {
         if enabled {
             self.sstatus.set_sie(enabled);
-            unsafe { 
+            unsafe {
                 sie::set_sext();
                 sie::set_ssoft();
                 sie::set_stimer();
             };
         } else {
             self.sstatus.set_sie(enabled);
-            unsafe { 
+            unsafe {
                 sie::clear_sext();
                 sie::clear_ssoft();
                 sie::clear_stimer();

+ 5 - 0
crates/eonix_hal/src/bootstrap.rs

@@ -20,3 +20,8 @@ impl BootStrapData {
         self.early_stack
     }
 }
+
+#[cfg(target_arch = "riscv64")]
+pub fn early_console_write(s: &str) {
+    crate::arch::bootstrap::early_console_write(s);
+}

+ 7 - 0
crates/eonix_hal/src/device.rs

@@ -0,0 +1,7 @@
+use cfg_if::cfg_if;
+
+cfg_if! {
+    if #[cfg(target_arch = "riscv64")] {
+        pub use crate::arch::fdt::FDT;
+    }
+}

+ 1 - 0
crates/eonix_hal/src/lib.rs

@@ -6,6 +6,7 @@ pub(crate) mod arch;
 
 pub mod bootstrap;
 pub mod context;
+pub mod device;
 pub mod mm;
 pub mod processor;
 pub mod trap;

+ 6 - 16
crates/eonix_hal/src/link.x.in

@@ -1,25 +1,15 @@
 PROVIDE(_stext = ORIGIN(REGION_TEXT));
 
 SECTIONS {
-    .text.dummy (NOLOAD) :
+    .text _stext :
     {
-        /*
-         * If we use _stext somewhere before its first appearance below, we
-         * need to define it as absolute here to avoid linker errors.
-         */
-        . = ABSOLUTE(_stext);
-
-    } > REGION_TEXT
-
-    .text _stext : AT(RAM) {
         __kernel_start = .;
         __stext = .;
 
         *(.text.entry);
         *(.text .text.*);
 
-        . = ALIGN(0x1000);
-    } > REGION_TEXT
+    } > REGION_TEXT AT> RAM
 
     __etext = .;
 
@@ -29,7 +19,7 @@ SECTIONS {
 
         *(.rodata .rodata.*);
 
-    } > REGION_RODATA
+    } > REGION_RODATA AT> RAM
 
     __erodata = .;
 
@@ -40,7 +30,7 @@ SECTIONS {
         *(.data .data.*);
         *(.got .got.plt);
 
-    } > REGION_DATA
+    } > REGION_DATA AT> RAM
 
     __edata = .;
 
@@ -51,7 +41,7 @@ SECTIONS {
         *(.bss .bss.*);
 
         . = ALIGN(0x1000);
-    } > REGION_BSS
+    } > REGION_BSS AT> RAM
 
     __ebss = .;
 
@@ -61,7 +51,7 @@ SECTIONS {
 
         KEEP(*(.eh_frame .eh_frame*));
 
-    } > REGION_EHFRAME
+    } > REGION_EHFRAME AT> RAM
 
     . = ALIGN(0x1000);
     __eeh_frame = .;

+ 5 - 1
crates/eonix_percpu/eonix_percpu_macros/src/lib.rs

@@ -121,6 +121,7 @@ fn define_percpu_shared_impl(
     attrs: TokenStream,
     item: TokenStream,
     get_percpu_pointer: fn(&Ident, &Type) -> TokenStream,
+    get_percpu_offset: fn(&Ident) -> TokenStream,
 ) -> TokenStream {
     if !attrs.is_empty() {
         panic!("`define_percpu_shared` attribute does not take any arguments");
@@ -136,6 +137,7 @@ fn define_percpu_shared_impl(
     let access_ident = format_ident!("_access_shared_{}", ident);
 
     let as_ptr = get_percpu_pointer(&inner_ident, &ty);
+    let get_offset = get_percpu_offset(&inner_ident);
 
     quote! {
         #[link_section = ".percpu"]
@@ -156,7 +158,7 @@ fn define_percpu_shared_impl(
             }
 
             pub fn get_for_cpu(&self, cpuid: usize) -> Option<& #ty > {
-                let offset = & #inner_ident as *const _ as usize;
+                let offset = #get_offset;
                 let base = ::eonix_percpu::PercpuArea::get_for(cpuid);
                 base.map(|base| unsafe { base.byte_add(offset).cast().as_ref() })
             }
@@ -205,6 +207,7 @@ pub fn define_percpu_shared_x86_64(
         attrs.into(),
         item.into(),
         arch_macros::x86_64::percpu::get_percpu_pointer,
+        arch_macros::x86_64::percpu::get_percpu_offset,
     )
     .into()
 }
@@ -231,6 +234,7 @@ pub fn define_percpu_shared_riscv64(
         attrs.into(),
         item.into(),
         arch_macros::riscv64::percpu::get_percpu_pointer,
+        arch_macros::riscv64::percpu::get_percpu_offset,
     )
     .into()
 }

+ 2 - 1
crates/eonix_runtime/src/task.rs

@@ -14,6 +14,7 @@ use core::{
     sync::atomic::{AtomicBool, AtomicU32, Ordering},
     task::{Context, Poll, Waker},
 };
+use eonix_hal::processor::CPU;
 use eonix_preempt::assert_preempt_enabled;
 use eonix_sync::Spin;
 use intrusive_collections::RBTreeAtomicLink;
@@ -89,7 +90,7 @@ impl Task {
             id: TaskId(ID.fetch_add(1, Ordering::Relaxed)),
             on_rq: AtomicBool::new(false),
             unparked: AtomicBool::new(false),
-            cpu: AtomicU32::new(0),
+            cpu: AtomicU32::new(CPU::local().cpuid() as u32),
             state: TaskState::new(TaskState::RUNNING),
             executor: AtomicUniqueRefCell::new(Some(executor)),
             execution_context,

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

@@ -1,4 +1,3 @@
-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;

+ 0 - 1
src/kernel_init.rs

@@ -33,7 +33,6 @@ pub fn setup_memory(data: &mut BootStrapData) {
         let attr = PageAttribute::PRESENT
             | PageAttribute::WRITE
             | PageAttribute::READ
-            | PageAttribute::HUGE
             | PageAttribute::GLOBAL;
 
         let page = GenericPage::alloc_in(&alloc);

+ 26 - 7
src/lib.rs

@@ -27,12 +27,12 @@ use core::{
     sync::atomic::{AtomicBool, Ordering},
 };
 use elf::ParsedElf32;
-use eonix_hal::{processor::CPU, traits::trap::IrqState, trap::disable_irqs_save};
+use eonix_hal::{processor::CPU, trap::disable_irqs_save};
+use eonix_log::ConsoleWrite;
 use eonix_mm::address::PRange;
 use eonix_runtime::{run::FutureRun, scheduler::Scheduler, task::Task};
 use kernel::{
     mem::GlobalPageAlloc,
-    pcie::init_pcie,
     task::{new_thread_runnable, KernelStack, ProcessBuilder, ProcessList, ThreadBuilder},
     vfs::{
         dentry::Dentry,
@@ -71,7 +71,23 @@ fn kernel_init(mut data: eonix_hal::bootstrap::BootStrapData) -> ! {
 
     BSP_OK.store(true, Ordering::Release);
 
-    init_pcie().expect("Unable to initialize PCIe bus");
+    #[cfg(target_arch = "riscv64")]
+    {
+        struct Console;
+
+        impl ConsoleWrite for Console {
+            fn write(&self, s: &str) {
+                eonix_hal::bootstrap::early_console_write(s);
+            }
+        }
+
+        eonix_log::set_console(Arc::new(Console));
+    }
+
+    #[cfg(target_arch = "x86_64")]
+    {
+        kernel::pcie::init_pcie().expect("Unable to initialize PCIe bus");
+    }
 
     // To satisfy the `Scheduler` "preempt count == 0" assertion.
     eonix_preempt::disable();
@@ -120,11 +136,14 @@ async fn init_process(early_kstack: PRange) {
 
     CharDevice::init().unwrap();
 
-    // We might want the serial initialized as soon as possible.
-    driver::serial::init().unwrap();
+    #[cfg(target_arch = "x86_64")]
+    {
+        // We might want the serial initialized as soon as possible.
+        driver::serial::init().unwrap();
 
-    driver::e1000e::register_e1000e_driver();
-    driver::ahci::register_ahci_driver();
+        driver::e1000e::register_e1000e_driver();
+        driver::ahci::register_ahci_driver();
+    }
 
     fs::tmpfs::init();
     fs::procfs::init();