diff --git a/.gitignore b/.gitignore index 55d19b18..c476fcdb 100644 --- a/.gitignore +++ b/.gitignore @@ -1,15 +1,18 @@ -/target +**/.* +!.github/ +!.vscode/settings.json + **/target **/*.rs.bk +*.img +*.log Cargo.lock + /rootfs /riscv_rootfs /prebuilt/linux/alpine* /prebuilt/linux/riscv64/prebuild* zCore/src/platform/riscv/boot/kernel-vars.ld -*.img -*.log -.idea + .DS_Store -.vscode/ __pycache__ diff --git a/rust-toolchain b/rust-toolchain deleted file mode 100644 index 3fe568ef..00000000 --- a/rust-toolchain +++ /dev/null @@ -1 +0,0 @@ -nightly-2022-01-20 diff --git a/rust-toolchain.toml b/rust-toolchain.toml new file mode 100644 index 00000000..e8908899 --- /dev/null +++ b/rust-toolchain.toml @@ -0,0 +1,4 @@ +[toolchain] +channel = "nightly-2022-01-20" +components = ["rust-src", "llvm-tools-preview", "rustfmt", "clippy"] +targets = ["riscv64gc-unknown-none-elf"] diff --git a/zCore/Cargo.toml b/zCore/Cargo.toml index 7849ff8d..99bb60bb 100644 --- a/zCore/Cargo.toml +++ b/zCore/Cargo.toml @@ -2,7 +2,7 @@ name = "zcore" version = "0.1.0" authors = ["PanQL ", "Yuekai Jia "] -edition = "2018" +edition = "2021" default-run = "zcore" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html @@ -77,6 +77,12 @@ rcore-fs-hostfs = { git = "https://github.com/rcore-os/rcore-fs", rev = "1a3246b [target.'cfg(target_os = "none")'.dependencies] buddy_system_allocator = "0.8" +# RISC-V +[target.'cfg(any(target_arch = "riscv32", target_arch = "riscv64"))'.dependencies] +riscv = { git = "https://github.com/rust-embedded/riscv", rev = "cd31989", features = [ + "inline-asm", +] } + # Bare-metal mode on x86_64 [target.'cfg(all(target_os = "none", target_arch = "x86_64"))'.dependencies] rboot = { git = "https://github.com/rcore-os/rboot.git", rev = "39d6e24", default-features = false } diff --git a/zCore/src/main.rs b/zCore/src/main.rs index 57b9a348..bef4d2a1 100644 --- a/zCore/src/main.rs +++ b/zCore/src/main.rs @@ -55,8 +55,6 @@ fn primary_main(config: kernel_hal::KernelConfig) { } } -#[allow(dead_code)] -#[cfg(not(feature = "libos"))] fn secondary_main() -> ! { while !STARTED.load(Ordering::SeqCst) {} // Don't print anything between previous line and next line. diff --git a/zCore/src/platform/riscv/boot/boot_d1.asm b/zCore/src/platform/riscv/boot/boot_d1.asm deleted file mode 100644 index a0cfaefc..00000000 --- a/zCore/src/platform/riscv/boot/boot_d1.asm +++ /dev/null @@ -1,19 +0,0 @@ -.equ PHY_MEM_OFS, 0xffffffff80000000 - - .section .data - .align 12 #12位对齐 -boot_page_table_sv39: - .zero 8 - - # d1 c906有扩展63:59位的页表项属性 - # 0x40000000 --> 0x40000000 - #.quad (1 << 62) | (1 << 61) | (1 << 60) | (0x40000 << 10) | 0xef - .quad (0x40000 << 10) | 0xef - - .zero 8 * 508 - - # 0xffffffff_80000000 --> 0x00000000 - # 0xffffffff_C0000000 --> 0x40000000 - .quad (0x00000 << 10) | 0xef - .quad (0x40000 << 10) | 0xef - diff --git a/zCore/src/platform/riscv/boot/boot_qemu.asm b/zCore/src/platform/riscv/boot/boot_qemu.asm deleted file mode 100644 index 3d236a1f..00000000 --- a/zCore/src/platform/riscv/boot/boot_qemu.asm +++ /dev/null @@ -1,18 +0,0 @@ -.equ PHY_MEM_OFS, 0xffffffff00000000 - - .section .data - .align 12 #12位对齐 -boot_page_table_sv39: - #1G的一个大页: 0x00000000_80000000 --> 0x80000000 - #1G的一个大页: 0xffffffff_80000000 --> 0x80000000 - - #前510项置0 - .zero 8 - .zero 8 - .quad (0x80000 << 10) | 0xef #0x80000000 --> 0x80000000 - - .zero 8 * 507 - #倒数第二项,PPN=0x80000(当转换为物理地址时还需左移12位), 标志位DAG_XWRV置1 - .quad (0x80000 << 10) | 0xef - .zero 8 - diff --git a/zCore/src/platform/riscv/boot/entry64.asm b/zCore/src/platform/riscv/boot/entry64.asm index eb6e4ae2..9302b39c 100644 --- a/zCore/src/platform/riscv/boot/entry64.asm +++ b/zCore/src/platform/riscv/boot/entry64.asm @@ -1,80 +1,71 @@ - .section .text.entry - .globl _start -_start: - #关中断 - csrw sie, zero +# 提供的全局符号 +# ------------------------------- +# /// 主核入口 +# fn _start(hartid: usize, device_tree_paddr: usize) -> !; + .global _start +# /// 副核入口 +# fn _secondary_hart_start(hartid: usize) -> !; + .global _secondary_hart_start +# /// 地址空间跃迁 +# fn jump_heigher(offset: usize); + .global _jump_higher - #关闭mmu - #csrw satp, zero - #BSS节清零 - la t0, sbss - la t1, ebss - bgeu t0, t1, secondary_hart_start +# 依赖的全局符号 +# ------------------------------- +# /// 主核入口 +# fn primary_rust_main(hartid: usize, device_tree_paddr: usize) -> !; +# +# /// 副核入口 +# fn secondary_rust_main(hartid: usize) -> !; -clear_bss_loop: - # sd: store double word (64 bits) - sd zero, (t0) - addi t0, t0, 8 - bltu t0, t1, clear_bss_loop + .section .text.entry -primary_hart: - call init_vm - lui t0, %hi(primary_rust_main) - addi t0, t0, %lo(primary_rust_main) - jr t0 +# 主核入口 +# 清零 bss 段,构造启动页表,然后跳转到高地址映射的主核主函数 +# ------------------------------- +_start: # fn _start(hartid: usize, device_tree_paddr: usize) -> ! {{ + csrw sie, zero # $sie = 0; // 关中断 + call select_stack # select_stack(hartid); + j primary_rust_main # primary_rust_main(hartid, device_tree_paddr) + # }} +# ------------------------------- +# 副核入口 +# 构造启动页表,然后跳转到高地址映射的副核主函数 +# ------------------------------- +_secondary_hart_start: # fn _secondary_hart_start(hartid: usize) -> ! {{ + csrw sie, zero # $sie = 0; // 关中断 + call select_stack # select_stack(hartid); + j secondary_rust_main # secondary_rust_main(hartid) + # }} +# ------------------------------- -.globl secondary_hart_start -secondary_hart_start: - csrw sie, zero - call init_vm - lui t0, %hi(secondary_rust_main) - addi t0, t0, %lo(secondary_rust_main) - jr t0 +# 根据线程号设置启动栈 +# ------------------------------- +select_stack: # fn select_stack(hartid: usize) {{ + mv t0, a0 # $t0 = hartid; + la sp, bootstacktop # $sp = bootstacktop; + beqz t0, 2f # if $t0 != 0 {{ + li t1, -4096*16 # $t1 = -4096*16; + # loop {{ +1: add sp, sp, t1 # $sp += $t1; + addi t0, t0, -1 # $t0 -= 1; + bgtz t0, 1b # if $t0 > 0 {{ continue; }} + # }} + # }} +2: ret # }} +# ------------------------------- -init_vm: - #la sp, bootstacktop - #call rust_main +# 从地址空间的低处跳到地址空间高处对应位置并挪动栈指针 +# ------------------------------- +_jump_higher: # fn jump_heigher(offset: usize) {{ + add ra, ra, a0 # $t0 += offset; + add sp, sp, a0 # $sp += offset; + ret # }} +# ------------------------------- - #可清零低12位地址 - lui t0, %hi(boot_page_table_sv39) - li t1, PHY_MEM_OFS # 立即数加载 - #计算出页表的物理地址 - sub t0, t0, t1 - - #右移12位,变为satp的PPN - srli t0, t0, 12 - - #satp的MODE设为Sv39 - li t1, 8 << 60 - - #写satp - or t0, t0, t1 - csrw satp, t0 - - #刷新TLB - sfence.vma - - # t0 = 0 - xor t0, t0, t0 - mv t1, a0 - beqz t1, 2f - li t2, 4096 * 16 -1: - add t0, t0, t2 - addi t1, t1, -1 - bgtz t1, 1b -2: - #此时在虚拟内存空间,设置sp为虚拟地址 - lui sp, %hi(bootstacktop) - sub sp, sp, t0 - ret - - .section .bss.stack - .align 12 - .global bootstack + .section .bss.bootstack + .align 12 bootstack: - .space 4096 * 160 - .global bootstacktop + .space 4096 * 160 bootstacktop: - diff --git a/zCore/src/platform/riscv/boot/linker64.ld b/zCore/src/platform/riscv/boot/linker64.ld index be810f02..19073d22 100644 --- a/zCore/src/platform/riscv/boot/linker64.ld +++ b/zCore/src/platform/riscv/boot/linker64.ld @@ -7,40 +7,38 @@ SECTIONS . = BASE_ADDRESS; start = .; + stext = .; .text : { - stext = .; *(.text.entry) - _copy_user_start = .; - *(.text.copy_user) - _copy_user_end = .; *(.text .text.*) - . = ALIGN(4K); - etext = .; } + . = ALIGN(4K); + etext = .; + srodata = .; .rodata : { - srodata = .; *(.rodata .rodata.*) - erodata = .; } + . = ALIGN(4K); + erodata = .; + sdata = .; .data : { - sdata = .; *(.data .data.*) - edata = .; - } - - .stack : { - *(.bss.stack) - . = ALIGN(4K); } + . = ALIGN(4K); + edata = .; .bss : { + *(.bss.bootstack) + + . = ALIGN(4K); sbss = .; *(.bss .bss.* .sbss) - . = ALIGN(4K); - ebss = .; } + . = ALIGN(4K); + ebss = .; + PROVIDE(end = .); } diff --git a/zCore/src/platform/riscv/entry.rs b/zCore/src/platform/riscv/entry.rs index cd1b25e7..354e4012 100644 --- a/zCore/src/platform/riscv/entry.rs +++ b/zCore/src/platform/riscv/entry.rs @@ -1,74 +1,136 @@ -#[cfg(feature = "board-qemu")] -global_asm!( - include_str!("boot/boot_qemu.asm"), - include_str!("boot/entry64.asm"), -); +use super::consts::PHYSICAL_MEMORY_OFFSET; +use core::{ + arch::{asm, global_asm}, + str::FromStr, +}; +use kernel_hal::{ + sbi::{hart_start, send_ipi, shutdown, SBI_SUCCESS}, + KernelConfig, +}; -#[cfg(feature = "board-d1")] -global_asm!( - include_str!("boot/boot_d1.asm"), - include_str!("boot/entry64.asm"), -); +global_asm!(include_str!("boot/entry64.asm")); -use super::consts::*; -use core::arch::{asm, global_asm}; -use core::str::FromStr; -use kernel_hal::arch::sbi::{hart_start, send_ipi, SBI_SUCCESS}; -use kernel_hal::KernelConfig; -const SMP: &str = core::env!("SMP"); // Get HART number from the environment variable +// 启动页表 +#[repr(align(4096))] +struct BootPageTable([usize; 512]); +static mut BOOT_PAGE_TABLE: BootPageTable = BootPageTable([0; 512]); + +// 各级页面容量 +const KIB_BITS: usize = 12; // 4KiB +const MIB_BITS: usize = KIB_BITS + 9; // 2MiB +const GIB_BITS: usize = MIB_BITS + 9; // 1GiB + +// 各级页号遮罩 +// const KIB_MASK: usize = !((1 << KIB_BITS) - 1); +// const MIB_MASK: usize = !((1 << MIB_BITS) - 1); +const GIB_MASK: usize = !((1 << GIB_BITS) - 1); +const SV39_MASK: usize = (1 << (GIB_BITS + 9)) - 1; + +/// 填充 `satp` +const MODE_SV39: usize = 8 << 60; + +/// 内核页属性 +const DAGXWRV: usize = 0xef; + +// 符号表 extern "C" { - fn secondary_hart_start(); + /// 内核入口 + fn _start(); + /// 副核入口 + fn _secondary_hart_start(); + /// 向上跳到距离为 `offset` 的新地址,继续执行 + fn _jump_higher(offset: usize); + /// bss 段起始地址 + fn sbss(); + /// bss 段结束地址 + fn ebss(); } #[no_mangle] pub extern "C" fn primary_rust_main(hartid: usize, device_tree_paddr: usize) -> ! { - unsafe { - asm!("mv tp, {0}", in(reg) hartid); - let mut sstatus: usize; - asm!("csrr {0}, sstatus", out(reg) sstatus); - sstatus |= 1 << 18; - asm!("csrw sstatus, {0}", in(reg) sstatus); - println!( - "boot hart: zCore rust_main(hartid: {}, device_tree_paddr: {:#x}) sstatus={:x}", - hartid, device_tree_paddr, sstatus - ); - }; + // 清零 bss 段 + let len = (ebss as usize - sbss as usize) / core::mem::size_of::(); + unsafe { core::slice::from_raw_parts_mut(sbss as *mut usize, len) }.fill(0); - let config = KernelConfig { - phys_to_virt_offset: PHYSICAL_MEMORY_OFFSET, - dtb_paddr: device_tree_paddr, - }; - for id in 0..usize::from_str(SMP).expect("can't parse SMP as usize.") { + // 内核的 GiB 页物理页号 + let start_ppn = ((_start as usize) & GIB_MASK) >> KIB_BITS; + // 内核 GiB 物理页帧在 GiB 页表中的序号 + let trampoline_pte_index = (_start as usize) >> GIB_BITS; + let mut pte_index = (PHYSICAL_MEMORY_OFFSET & SV39_MASK) >> GIB_BITS; + // 容纳内核的页表项 + let pte = (start_ppn << 10) | DAGXWRV; + + // 构造启动页表 + // # TODO d1 c906 有扩展 63:59 位的页表项属性 + // #.quad (1 << 62) | (1 << 61) | (1 << 60) | (0x40000 << 10) | 0xef + unsafe { + *BOOT_PAGE_TABLE.0.get_unchecked_mut(trampoline_pte_index) = pte; + let mut page = DAGXWRV; + while pte_index < 512 { + *BOOT_PAGE_TABLE.0.get_unchecked_mut(pte_index) = page; + page += 1 << (GIB_BITS + 10 - KIB_BITS); + pte_index += 1; + } + } + + // 启动副核 + for id in 0..usize::from_str(core::env!("SMP")).expect("can't parse SMP as usize.") { if id != hartid { - let err_code = hart_start( - id, - secondary_hart_start as usize - PHYSICAL_MEMORY_OFFSET, // cal physical address - 0, - ); + let err_code = hart_start(id, _secondary_hart_start as _, 0); if err_code != SBI_SUCCESS { panic!("start hart{} failed. error code={}", id, err_code); } - let hart_mask: usize = 1 << id; - let err_code = send_ipi(&hart_mask as *const _ as usize); + let hart_mask = 1usize << id; + let err_code = send_ipi(&hart_mask as *const _ as _); if err_code != SBI_SUCCESS { panic!("send ipi to hart{} failed. error code={}", id, err_code); } } } - crate::primary_main(config); - unreachable!() + + // 使能启动页表 + let sstatus = unsafe { BOOT_PAGE_TABLE.launch(hartid) }; + println!( + " +boot hart: zCore rust_main(hartid: {}, device_tree_paddr: {:#x}) +sstatus = {:#x}", + hartid, device_tree_paddr, sstatus + ); + + crate::primary_main(KernelConfig { + phys_to_virt_offset: PHYSICAL_MEMORY_OFFSET, + dtb_paddr: device_tree_paddr, + }); + shutdown() } -// Don't print in this function and use console_write_early if necessary #[no_mangle] pub extern "C" fn secondary_rust_main(hartid: usize) -> ! { - unsafe { - asm!("mv tp, {0}", in(reg) hartid); - let mut sstatus: usize; - asm!("csrr {0}, sstatus", out(reg) sstatus); - sstatus |= 1 << 18; // set SUM=1 - asm!("csrw sstatus, {0}", in(reg) sstatus); - }; - crate::secondary_main(); + let _ = unsafe { BOOT_PAGE_TABLE.launch(hartid) }; + crate::secondary_main() +} + +impl BootPageTable { + /// 设置启动页表,并跃迁到高地址。 + /// + /// # Safety + /// + /// 内含极度危险的地址空间跃迁操作,必须内联。 + #[inline(always)] + unsafe fn launch(&self, hartid: usize) -> usize { + // 启动页表的页号,将填写到 `satp` + let satp = MODE_SV39 | ((self.0.as_ptr() as usize) >> KIB_BITS); + // 启动地址转换 + riscv::register::satp::write(satp); + riscv::asm::sfence_vma_all(); + // 跳到高页面对应位置 + _jump_higher(PHYSICAL_MEMORY_OFFSET); + // 设置线程指针 + asm!("mv tp, {}", in(reg) hartid); + // 设置内核可访问用户页 + let sstatus: usize; + asm!("csrrsi {}, sstatus, 18", out(reg) sstatus); + sstatus + } }