From 0a4f6dbf388b4a9a5d5738b5872339abcd032dff Mon Sep 17 00:00:00 2001 From: YdrMaster Date: Wed, 20 Apr 2022 04:53:04 +0800 Subject: [PATCH 1/6] =?UTF-8?q?refactor(zCore):=20=E6=95=B4=E7=90=86=20ris?= =?UTF-8?q?cv=20=E5=90=AF=E5=8A=A8=E6=B5=81=E7=A8=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- zCore/src/main.rs | 2 - zCore/src/platform/riscv/boot/entry64.asm | 164 +++++++++++++--------- zCore/src/platform/riscv/boot/linker64.ld | 32 ++--- zCore/src/platform/riscv/entry.rs | 67 ++++----- 4 files changed, 143 insertions(+), 122 deletions(-) diff --git a/zCore/src/main.rs b/zCore/src/main.rs index a774f685..4fde1b6d 100644 --- a/zCore/src/main.rs +++ b/zCore/src/main.rs @@ -58,8 +58,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/entry64.asm b/zCore/src/platform/riscv/boot/entry64.asm index ada62558..554f90cc 100644 --- a/zCore/src/platform/riscv/boot/entry64.asm +++ b/zCore/src/platform/riscv/boot/entry64.asm @@ -1,80 +1,116 @@ - .section .text.entry - .globl _start -_start: - #关中断 - csrw sie, zero +# 提供的全局符号 +# -------------------------------------- +# 主核入口 +# fn _start(hartid: usize, device_tree_paddr: usize) -> !; + .globl _start +# 副核入口 +# fn _secondary_hart_start(hartid: usize) -> !; + .globl _secondary_hart_start +# 启动栈(160 页) +# RISC-V 架构栈从高地址向低地址增长 +# const bootstack: *const u8; # 栈底 +# const bootstacktop: *mut u8; # 栈顶 + .global bootstack + .global bootstacktop - #关闭mmu - #csrw satp, zero - #BSS节清零 - la t0, sbss - la t1, ebss - bgeu t0, t1, secondary_hart_start +# 依赖的全局符号 +# -------------------------------------- +# /// 用于启动的 Sv39 1GiB 页表页 +# const boot_page_table_sv39: *const u8; +# +# /// 主核启动函数 +# fn primary_rust_main(hartid: usize, device_tree_paddr: usize) -> !; +# +# /// 副核启动函数 +# fn secondary_rust_main() -> !; -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 +# 跨页跳转 +# 加载 `symbol` 的地址并转换到高地址映射,然后跳转 +# -------------------------------------- +.macro jump_cross symbol # + lui t0, %hi(\symbol) # + addi t0, t0, %lo(\symbol) # + jr t0 # +.endm # +# -------------------------------------- +# 主核入口 +# 清零 bss 段,构造启动页表,然后跳转到高地址映射的主核主函数 +# -------------------------------------- +_start: # fn _start(hartid: usize, device_tree_paddr: usize) -> ! {{ + csrw sie, zero # $sie = 0; // 关中断 + # // 清空 bss 段 + la t0, sbss # $t0 = &sbss; + la t1, ebss # $t1 = &ebss; + # loop {{ +1: sd zero, (t0) # *$t0 = 0usize; + addi t0, t0, 8 # $t0 += 8; + bltu t0, t1, 1b # if $t0 < $t1 {{ continue; }} + # }} + call init_vm # init_vm(hartid); // 启动虚存,并做一些其他初始化工作 + jump_cross primary_rust_main # primary_rust_main(hartid, device_tree_paddr) + # }} +# -------------------------------------- -.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 +# 副核入口 +# 构造启动页表,然后跳转到高地址映射的副核主函数 +# -------------------------------------- +_secondary_hart_start: # fn _secondary_hart_start(hartid: usize) -> ! {{ + csrw sie, zero # $sie = 0; // 关中断 + call init_vm # init_vm(hartid); // 启动虚存,并做一些其他初始化工作 + jump_cross secondary_rust_main # secondary_rust_main() + # }} +# -------------------------------------- +# 构造启动页表并启用地址映射 +# -------------------------------------- init_vm: - #la sp, bootstacktop - #call rust_main + .equ SATP_MODE_SV39, 8 << 60 + # 可清零低12位地址 + lui t0, %hi(boot_page_table_sv39) + li t1, PHY_MEM_OFS # 立即数加载 + # 计算出页表的物理地址 + sub t0, t0, t1 - #可清零低12位地址 - lui t0, %hi(boot_page_table_sv39) - li t1, PHY_MEM_OFS #立即数加载 - #计算出页表的物理地址 - sub t0, t0, t1 + # 右移12位,变为satp的PPN + srli t0, t0, 12 - #右移12位,变为satp的PPN - srli t0, t0, 12 + # satp的MODE设为Sv39 + li t1, SATP_MODE_SV39 + or t0, t0, t1 + csrw satp, t0 - #satp的MODE设为Sv39 - li t1, 8 << 60 + # 刷新TLB + sfence.vma - #写satp - or t0, t0, t1 - csrw satp, t0 + # 立即跳到高地址 + li t1, PHY_MEM_OFS + la t0, 1f + add t0, t0, t1 + jr t0 - #刷新TLB - sfence.vma +1: mv t0, zero + mv t1, a0 + beqz t1, 2f - # 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 + li t2, 4096 * 16 +1: add t0, t0, t2 + addi t1, t1, -1 + bgtz t1, 1b - .section .bss.stack - .align 12 - .global bootstack + # 此时在虚拟内存空间,设置 sp 为虚拟地址 +2: lui sp, %hi(bootstacktop) + sub sp, sp, t0 + + mv tp, a0 + csrrsi x0, sstatus, 18 + ret +# -------------------------------------- + + .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..ac148f06 100644 --- a/zCore/src/platform/riscv/entry.rs +++ b/zCore/src/platform/riscv/entry.rs @@ -10,65 +10,54 @@ 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 - -extern "C" { - fn secondary_hart_start(); -} +use super::consts::PHYSICAL_MEMORY_OFFSET; +use core::{ + arch::{asm, global_asm}, + str::FromStr, +}; +use kernel_hal::{ + arch::sbi::{hart_start, send_ipi, SBI_SUCCESS}, + KernelConfig, +}; #[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 - ); - }; + let sstatus: usize; + unsafe { asm!("csrr {0}, sstatus", out(reg) sstatus) }; + println!( + "boot hart: zCore rust_main(hartid: {}, device_tree_paddr: {:#x}) sstatus={:#x}", + hartid, device_tree_paddr, sstatus + ); - 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.") { + for id in 0..usize::from_str(core::env!("SMP")).expect("can't parse SMP as usize.") { if id != hartid { + extern "C" { + fn _secondary_hart_start(); + } let err_code = hart_start( id, - secondary_hart_start as usize - PHYSICAL_MEMORY_OFFSET, // cal physical address + _secondary_hart_start as usize - PHYSICAL_MEMORY_OFFSET, // cal physical address 0, ); if err_code != SBI_SUCCESS { panic!("start hart{} failed. error code={}", id, err_code); } - let hart_mask: usize = 1 << id; + let hart_mask = 1usize << id; let err_code = send_ipi(&hart_mask as *const _ as usize); if err_code != SBI_SUCCESS { panic!("send ipi to hart{} failed. error code={}", id, err_code); } } } - crate::primary_main(config); + + crate::primary_main(KernelConfig { + phys_to_virt_offset: PHYSICAL_MEMORY_OFFSET, + dtb_paddr: device_tree_paddr, + }); unreachable!() } -// 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(); +pub extern "C" fn secondary_rust_main() -> ! { + crate::secondary_main() } From 1750123a36e41a8866c4ba686f99c63e9bb3dd83 Mon Sep 17 00:00:00 2001 From: YdrMaster Date: Wed, 20 Apr 2022 09:41:43 +0800 Subject: [PATCH 2/6] =?UTF-8?q?docs(zCore):=20=E8=A1=A5=E5=85=A8=20riscv?= =?UTF-8?q?=20=E5=90=AF=E5=8A=A8=E8=BF=87=E7=A8=8B=E6=B3=A8=E9=87=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- zCore/src/platform/riscv/boot/entry64.asm | 116 ++++++++++------------ 1 file changed, 52 insertions(+), 64 deletions(-) diff --git a/zCore/src/platform/riscv/boot/entry64.asm b/zCore/src/platform/riscv/boot/entry64.asm index 554f90cc..07b96a74 100644 --- a/zCore/src/platform/riscv/boot/entry64.asm +++ b/zCore/src/platform/riscv/boot/entry64.asm @@ -29,84 +29,72 @@ # 跨页跳转 # 加载 `symbol` 的地址并转换到高地址映射,然后跳转 # -------------------------------------- -.macro jump_cross symbol # - lui t0, %hi(\symbol) # - addi t0, t0, %lo(\symbol) # - jr t0 # -.endm # +.macro jump_cross symbol # + lui t0, %hi(\symbol) # + addi t0, t0, %lo(\symbol) # + jr t0 # +.endm # # -------------------------------------- # 主核入口 # 清零 bss 段,构造启动页表,然后跳转到高地址映射的主核主函数 # -------------------------------------- -_start: # fn _start(hartid: usize, device_tree_paddr: usize) -> ! {{ - csrw sie, zero # $sie = 0; // 关中断 - # // 清空 bss 段 - la t0, sbss # $t0 = &sbss; - la t1, ebss # $t1 = &ebss; - # loop {{ -1: sd zero, (t0) # *$t0 = 0usize; - addi t0, t0, 8 # $t0 += 8; - bltu t0, t1, 1b # if $t0 < $t1 {{ continue; }} - # }} - call init_vm # init_vm(hartid); // 启动虚存,并做一些其他初始化工作 - jump_cross primary_rust_main # primary_rust_main(hartid, device_tree_paddr) - # }} +_start: # fn _start(hartid: usize, device_tree_paddr: usize) -> ! {{ + csrw sie, zero # $sie = 0; // 关中断 + # // 清空 bss 段 + la t0, sbss # $t0 = sbss; + la t1, ebss # $t1 = ebss; + # loop {{ +1: sd zero, (t0) # *$t0 = 0usize; + addi t0, t0, 8 # $t0 += 8; + bltu t0, t1, 1b # if $t0 < $t1 {{ continue; }} + # }} + call init_vm # init_vm(hartid); // 启动虚存,并做一些其他初始化工作 + jump_cross 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 init_vm # init_vm(hartid); // 启动虚存,并做一些其他初始化工作 - jump_cross secondary_rust_main # secondary_rust_main() - # }} +_secondary_hart_start: # fn _secondary_hart_start(hartid: usize) -> ! {{ + csrw sie, zero # $sie = 0; // 关中断 + call init_vm # init_vm(hartid); // 启动虚存,并做一些其他初始化工作 + jump_cross secondary_rust_main # secondary_rust_main() + # }} # -------------------------------------- # 构造启动页表并启用地址映射 # -------------------------------------- -init_vm: - .equ SATP_MODE_SV39, 8 << 60 - # 可清零低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, SATP_MODE_SV39 - or t0, t0, t1 - csrw satp, t0 - - # 刷新TLB - sfence.vma - - # 立即跳到高地址 - li t1, PHY_MEM_OFS - la t0, 1f - add t0, t0, t1 - jr t0 - -1: mv t0, zero - mv t1, a0 - beqz t1, 2f - - li t2, 4096 * 16 -1: add t0, t0, t2 - addi t1, t1, -1 - bgtz t1, 1b - - # 此时在虚拟内存空间,设置 sp 为虚拟地址 -2: lui sp, %hi(bootstacktop) - sub sp, sp, t0 - - mv tp, a0 - csrrsi x0, sstatus, 18 - ret +init_vm: # fn init_vm(hartid: usize) {{ + .equ SATP_MODE_SV39, 8 << 60 # const SATP_MODE_SV39: usize = 8 << 60; + # // 构造并使能启动页表 + li t1, SATP_MODE_SV39 # $t1 = SATP_MODE_SV39; + la t0, boot_page_table_sv39 # $t0 = boot_page_table_sv39; + srli t0, t0, 12 # $t0 >>= 12; + or t0, t0, t1 # $t0 |= $t1; + csrw satp, t0 # $satp = $t0; + sfence.vma # // 刷新 TLB + # // 立即跳到高地址 + li t1, PHY_MEM_OFS # $t1 = PHY_MEM_OFS; + la t0, 1f # $t0 = @1f; + add t0, t0, t1 # $t0 += $t1; + jr t0 # // 跳到高映射的虚地址 + # // 设置启动栈 +1: mv t0, zero # $t0 = 0; + mv t1, a0 # $t1 = hartid; + beqz t1, 2f # if $t1 == 0 {{ + li t2, 4096 * 16 # $t2 = 4096 * 16; +1: add t0, t0, t2 # $t0 += $t2; + addi t1, t1, -1 # $t1 -= 1; + bgtz t1, 1b # if $t1 > 0 {{ continue; }} + # }} +2: lui sp, %hi(bootstacktop) # $sp = bootstacktop; + sub sp, sp, t0 # $sp -= $t0; + # // 初始化其他东西 + mv tp, a0 # // 设置线程指针 + csrrsi x0, sstatus, 18 # // 使能内核访问用户页 + ret # }} # -------------------------------------- .section .bss.bootstack From 0fc50e5996a4448121f7d8f3987e9c5a61098fc9 Mon Sep 17 00:00:00 2001 From: YdrMaster Date: Thu, 21 Apr 2022 04:46:25 +0800 Subject: [PATCH 3/6] =?UTF-8?q?build:=20=E4=BF=AE=E6=94=B9=E4=B8=80?= =?UTF-8?q?=E4=BA=9B=E9=85=8D=E7=BD=AE=E6=96=87=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 13 ++++++++----- rust-toolchain | 1 - rust-toolchain.toml | 4 ++++ 3 files changed, 12 insertions(+), 6 deletions(-) delete mode 100644 rust-toolchain create mode 100644 rust-toolchain.toml 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"] From b1c89d7cfedc5772b5b84a2a292c8612b6c89d77 Mon Sep 17 00:00:00 2001 From: YdrMaster Date: Thu, 21 Apr 2022 05:03:19 +0800 Subject: [PATCH 4/6] =?UTF-8?q?perf(zCore):=20=E4=BC=98=E5=8C=96=E5=90=AF?= =?UTF-8?q?=E5=8A=A8=E6=A0=88=E8=AE=BE=E7=BD=AE=E6=93=8D=E4=BD=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- zCore/src/platform/riscv/boot/boot_d1.asm | 19 ++++------- zCore/src/platform/riscv/boot/boot_qemu.asm | 13 ++------ zCore/src/platform/riscv/boot/entry64.asm | 37 ++++++++++----------- 3 files changed, 27 insertions(+), 42 deletions(-) diff --git a/zCore/src/platform/riscv/boot/boot_d1.asm b/zCore/src/platform/riscv/boot/boot_d1.asm index a0cfaefc..04866ae9 100644 --- a/zCore/src/platform/riscv/boot/boot_d1.asm +++ b/zCore/src/platform/riscv/boot/boot_d1.asm @@ -1,19 +1,12 @@ .equ PHY_MEM_OFS, 0xffffffff80000000 .section .data - .align 12 #12位对齐 + .align 12 boot_page_table_sv39: - .zero 8 - - # d1 c906有扩展63:59位的页表项属性 - # 0x40000000 --> 0x40000000 + # TODO d1 c906 有扩展 63:59 位的页表项属性 #.quad (1 << 62) | (1 << 61) | (1 << 60) | (0x40000 << 10) | 0xef - .quad (0x40000 << 10) | 0xef - + .zero 8 + .quad (0x40000 << 10) | 0xef # 0x0000_0000_4000_0000 --> 0x4000_0000 .zero 8 * 508 - - # 0xffffffff_80000000 --> 0x00000000 - # 0xffffffff_C0000000 --> 0x40000000 - .quad (0x00000 << 10) | 0xef - .quad (0x40000 << 10) | 0xef - + .quad (0x00000 << 10) | 0xef # 0xffff_ffff_8000_0000 --> 0x0000_0000 + .quad (0x40000 << 10) | 0xef # 0xffff_ffff_c000_0000 --> 0x4000_0000 diff --git a/zCore/src/platform/riscv/boot/boot_qemu.asm b/zCore/src/platform/riscv/boot/boot_qemu.asm index 3d236a1f..2a9a9570 100644 --- a/zCore/src/platform/riscv/boot/boot_qemu.asm +++ b/zCore/src/platform/riscv/boot/boot_qemu.asm @@ -1,18 +1,11 @@ .equ PHY_MEM_OFS, 0xffffffff00000000 .section .data - .align 12 #12位对齐 + .align 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 - + .quad (0x80000 << 10) | 0xef #0x0000_0000_8000_0000 --> 0x8000_0000 .zero 8 * 507 - #倒数第二项,PPN=0x80000(当转换为物理地址时还需左移12位), 标志位DAG_XWRV置1 - .quad (0x80000 << 10) | 0xef + .quad (0x80000 << 10) | 0xef #0xffff_ffff_8000_0000 --> 0x8000_0000 .zero 8 - diff --git a/zCore/src/platform/riscv/boot/entry64.asm b/zCore/src/platform/riscv/boot/entry64.asm index 07b96a74..eb49c8a3 100644 --- a/zCore/src/platform/riscv/boot/entry64.asm +++ b/zCore/src/platform/riscv/boot/entry64.asm @@ -40,16 +40,16 @@ # 清零 bss 段,构造启动页表,然后跳转到高地址映射的主核主函数 # -------------------------------------- _start: # fn _start(hartid: usize, device_tree_paddr: usize) -> ! {{ - csrw sie, zero # $sie = 0; // 关中断 + csrw sie, zero # $sie = 0; // 关中断 # // 清空 bss 段 - la t0, sbss # $t0 = sbss; - la t1, ebss # $t1 = ebss; + la t0, sbss # $t0 = sbss; + la t1, ebss # $t1 = ebss; # loop {{ -1: sd zero, (t0) # *$t0 = 0usize; - addi t0, t0, 8 # $t0 += 8; - bltu t0, t1, 1b # if $t0 < $t1 {{ continue; }} +1: sd zero, (t0) # *$t0 = 0usize; + addi t0, t0, 8 # $t0 += 8; + bltu t0, t1, 1b # if $t0 < $t1 {{ continue; }} # }} - call init_vm # init_vm(hartid); // 启动虚存,并做一些其他初始化工作 + call init_vm # init_vm(hartid); // 启动虚存,并做一些其他初始化工作 jump_cross primary_rust_main # primary_rust_main(hartid, device_tree_paddr) # }} # -------------------------------------- @@ -59,7 +59,7 @@ _start: # fn _start(hartid: usize, device_tree_paddr # -------------------------------------- _secondary_hart_start: # fn _secondary_hart_start(hartid: usize) -> ! {{ csrw sie, zero # $sie = 0; // 关中断 - call init_vm # init_vm(hartid); // 启动虚存,并做一些其他初始化工作 + call init_vm # init_vm(hartid); // 启动虚存,并做一些其他初始化工作 jump_cross secondary_rust_main # secondary_rust_main() # }} # -------------------------------------- @@ -81,18 +81,17 @@ init_vm: # fn init_vm(hartid: usize) {{ add t0, t0, t1 # $t0 += $t1; jr t0 # // 跳到高映射的虚地址 # // 设置启动栈 -1: mv t0, zero # $t0 = 0; - mv t1, a0 # $t1 = hartid; - beqz t1, 2f # if $t1 == 0 {{ - li t2, 4096 * 16 # $t2 = 4096 * 16; -1: add t0, t0, t2 # $t0 += $t2; - addi t1, t1, -1 # $t1 -= 1; - bgtz t1, 1b # if $t1 > 0 {{ continue; }} +1: lui sp, %hi(bootstacktop) # $sp = bootstacktop; + mv t0, a0 # $t0 = hartid; + 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: lui sp, %hi(bootstacktop) # $sp = bootstacktop; - sub sp, sp, t0 # $sp -= $t0; - # // 初始化其他东西 - mv tp, a0 # // 设置线程指针 +2: mv tp, a0 # // 设置线程指针 csrrsi x0, sstatus, 18 # // 使能内核访问用户页 ret # }} # -------------------------------------- From fde18af386440ff0512fa55492c1a534ee5a0ed4 Mon Sep 17 00:00:00 2001 From: YdrMaster Date: Fri, 22 Apr 2022 00:29:52 +0800 Subject: [PATCH 5/6] =?UTF-8?q?refactor(zCore):=20=E5=90=AF=E5=8A=A8?= =?UTF-8?q?=E8=BF=87=E7=A8=8B=E5=AE=8C=E5=85=A8=20rust=20=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit todo: 适配 d1 --- zCore/Cargo.toml | 8 +- zCore/src/platform/riscv/boot/entry64.asm | 130 ++++++++-------------- zCore/src/platform/riscv/entry.rs | 125 ++++++++++++++++----- 3 files changed, 151 insertions(+), 112 deletions(-) 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/platform/riscv/boot/entry64.asm b/zCore/src/platform/riscv/boot/entry64.asm index eb49c8a3..9302b39c 100644 --- a/zCore/src/platform/riscv/boot/entry64.asm +++ b/zCore/src/platform/riscv/boot/entry64.asm @@ -1,100 +1,68 @@ # 提供的全局符号 -# -------------------------------------- -# 主核入口 +# ------------------------------- +# /// 主核入口 # fn _start(hartid: usize, device_tree_paddr: usize) -> !; - .globl _start -# 副核入口 + .global _start +# /// 副核入口 # fn _secondary_hart_start(hartid: usize) -> !; - .globl _secondary_hart_start -# 启动栈(160 页) -# RISC-V 架构栈从高地址向低地址增长 -# const bootstack: *const u8; # 栈底 -# const bootstacktop: *mut u8; # 栈顶 - .global bootstack - .global bootstacktop + .global _secondary_hart_start +# /// 地址空间跃迁 +# fn jump_heigher(offset: usize); + .global _jump_higher # 依赖的全局符号 -# -------------------------------------- -# /// 用于启动的 Sv39 1GiB 页表页 -# const boot_page_table_sv39: *const u8; -# -# /// 主核启动函数 +# ------------------------------- +# /// 主核入口 # fn primary_rust_main(hartid: usize, device_tree_paddr: usize) -> !; # -# /// 副核启动函数 -# fn secondary_rust_main() -> !; +# /// 副核入口 +# fn secondary_rust_main(hartid: usize) -> !; .section .text.entry -# 跨页跳转 -# 加载 `symbol` 的地址并转换到高地址映射,然后跳转 -# -------------------------------------- -.macro jump_cross symbol # - lui t0, %hi(\symbol) # - addi t0, t0, %lo(\symbol) # - jr t0 # -.endm # -# -------------------------------------- - # 主核入口 # 清零 bss 段,构造启动页表,然后跳转到高地址映射的主核主函数 -# -------------------------------------- -_start: # fn _start(hartid: usize, device_tree_paddr: usize) -> ! {{ - csrw sie, zero # $sie = 0; // 关中断 - # // 清空 bss 段 - la t0, sbss # $t0 = sbss; - la t1, ebss # $t1 = ebss; - # loop {{ -1: sd zero, (t0) # *$t0 = 0usize; - addi t0, t0, 8 # $t0 += 8; - bltu t0, t1, 1b # if $t0 < $t1 {{ continue; }} - # }} - call init_vm # init_vm(hartid); // 启动虚存,并做一些其他初始化工作 - jump_cross primary_rust_main # primary_rust_main(hartid, device_tree_paddr) - # }} -# -------------------------------------- +# ------------------------------- +_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 init_vm # init_vm(hartid); // 启动虚存,并做一些其他初始化工作 - jump_cross secondary_rust_main # secondary_rust_main() - # }} -# -------------------------------------- +# ------------------------------- +_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) + # }} +# ------------------------------- -# 构造启动页表并启用地址映射 -# -------------------------------------- -init_vm: # fn init_vm(hartid: usize) {{ - .equ SATP_MODE_SV39, 8 << 60 # const SATP_MODE_SV39: usize = 8 << 60; - # // 构造并使能启动页表 - li t1, SATP_MODE_SV39 # $t1 = SATP_MODE_SV39; - la t0, boot_page_table_sv39 # $t0 = boot_page_table_sv39; - srli t0, t0, 12 # $t0 >>= 12; - or t0, t0, t1 # $t0 |= $t1; - csrw satp, t0 # $satp = $t0; - sfence.vma # // 刷新 TLB - # // 立即跳到高地址 - li t1, PHY_MEM_OFS # $t1 = PHY_MEM_OFS; - la t0, 1f # $t0 = @1f; - add t0, t0, t1 # $t0 += $t1; - jr t0 # // 跳到高映射的虚地址 - # // 设置启动栈 -1: lui sp, %hi(bootstacktop) # $sp = bootstacktop; - mv t0, a0 # $t0 = hartid; - 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: mv tp, a0 # // 设置线程指针 - csrrsi x0, sstatus, 18 # // 使能内核访问用户页 - ret # }} -# -------------------------------------- +# 根据线程号设置启动栈 +# ------------------------------- +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 # }} +# ------------------------------- + +# 从地址空间的低处跳到地址空间高处对应位置并挪动栈指针 +# ------------------------------- +_jump_higher: # fn jump_heigher(offset: usize) {{ + add ra, ra, a0 # $t0 += offset; + add sp, sp, a0 # $sp += offset; + ret # }} +# ------------------------------- .section .bss.bootstack .align 12 diff --git a/zCore/src/platform/riscv/entry.rs b/zCore/src/platform/riscv/entry.rs index ac148f06..ca9086fe 100644 --- a/zCore/src/platform/riscv/entry.rs +++ b/zCore/src/platform/riscv/entry.rs @@ -1,63 +1,128 @@ -#[cfg(feature = "board-qemu")] -global_asm!( - include_str!("boot/boot_qemu.asm"), - include_str!("boot/entry64.asm"), -); - -#[cfg(feature = "board-d1")] -global_asm!( - include_str!("boot/boot_d1.asm"), - include_str!("boot/entry64.asm"), -); - use super::consts::PHYSICAL_MEMORY_OFFSET; use core::{ arch::{asm, global_asm}, str::FromStr, }; use kernel_hal::{ - arch::sbi::{hart_start, send_ipi, SBI_SUCCESS}, + sbi::{hart_start, send_ipi, shutdown, SBI_SUCCESS}, KernelConfig, }; +global_asm!(include_str!("boot/entry64.asm")); + +// 启动页表 +#[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); + +/// 填充 `satp` +const MODE_SV39: usize = 8 << 60; + +/// 内核页属性 +const DAGXWRV: usize = 0xef; + +// 符号表 +extern "C" { + /// 内核入口 + 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) -> ! { - let sstatus: usize; - unsafe { asm!("csrr {0}, sstatus", out(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); + // 内核的 GiB 页物理页号 + let start_ppn = ((_start as usize) & GIB_MASK) >> KIB_BITS; + // 内核 GiB 物理页帧在 GiB 页表中的序号 + let start_pte_index = (_start as usize) >> GIB_BITS; + // 容纳内核的页表项 + let pte = (start_ppn << 10) | DAGXWRV; + + // 构造启动页表 + unsafe { + // 0x0000_0000_8000_0000 -> 0x8000_0000 + *BOOT_PAGE_TABLE.0.get_unchecked_mut(start_pte_index) = pte; + // 0xffff_ffff_8000_0000 -> 0x8000_0000 + *BOOT_PAGE_TABLE.0.get_unchecked_mut(510) = pte; + } + + // 启动副核 for id in 0..usize::from_str(core::env!("SMP")).expect("can't parse SMP as usize.") { if id != hartid { - extern "C" { - fn _secondary_hart_start(); - } - 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 = 1usize << id; - let err_code = send_ipi(&hart_mask as *const _ as usize); + 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); } } } + 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, }); - unreachable!() + shutdown() } #[no_mangle] -pub extern "C" fn secondary_rust_main() -> ! { +pub extern "C" fn secondary_rust_main(hartid: usize) -> ! { + 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 + } +} From 010f316a22e3a62d47420a65738ff73ab02e293e Mon Sep 17 00:00:00 2001 From: YdrMaster Date: Fri, 22 Apr 2022 04:54:59 +0800 Subject: [PATCH 6/6] =?UTF-8?q?refactor(zCore):=20riscv=20=E5=90=84?= =?UTF-8?q?=E5=BC=80=E5=8F=91=E6=9D=BF=E5=85=BC=E5=AE=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- zCore/src/platform/riscv/boot/boot_d1.asm | 12 ------------ zCore/src/platform/riscv/boot/boot_qemu.asm | 11 ----------- zCore/src/platform/riscv/entry.rs | 18 +++++++++++++----- 3 files changed, 13 insertions(+), 28 deletions(-) delete mode 100644 zCore/src/platform/riscv/boot/boot_d1.asm delete mode 100644 zCore/src/platform/riscv/boot/boot_qemu.asm 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 04866ae9..00000000 --- a/zCore/src/platform/riscv/boot/boot_d1.asm +++ /dev/null @@ -1,12 +0,0 @@ -.equ PHY_MEM_OFS, 0xffffffff80000000 - - .section .data - .align 12 -boot_page_table_sv39: - # TODO d1 c906 有扩展 63:59 位的页表项属性 - #.quad (1 << 62) | (1 << 61) | (1 << 60) | (0x40000 << 10) | 0xef - .zero 8 - .quad (0x40000 << 10) | 0xef # 0x0000_0000_4000_0000 --> 0x4000_0000 - .zero 8 * 508 - .quad (0x00000 << 10) | 0xef # 0xffff_ffff_8000_0000 --> 0x0000_0000 - .quad (0x40000 << 10) | 0xef # 0xffff_ffff_c000_0000 --> 0x4000_0000 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 2a9a9570..00000000 --- a/zCore/src/platform/riscv/boot/boot_qemu.asm +++ /dev/null @@ -1,11 +0,0 @@ -.equ PHY_MEM_OFS, 0xffffffff00000000 - - .section .data - .align 12 -boot_page_table_sv39: - .zero 8 - .zero 8 - .quad (0x80000 << 10) | 0xef #0x0000_0000_8000_0000 --> 0x8000_0000 - .zero 8 * 507 - .quad (0x80000 << 10) | 0xef #0xffff_ffff_8000_0000 --> 0x8000_0000 - .zero 8 diff --git a/zCore/src/platform/riscv/entry.rs b/zCore/src/platform/riscv/entry.rs index ca9086fe..354e4012 100644 --- a/zCore/src/platform/riscv/entry.rs +++ b/zCore/src/platform/riscv/entry.rs @@ -25,6 +25,7 @@ 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; @@ -55,16 +56,22 @@ pub extern "C" fn primary_rust_main(hartid: usize, device_tree_paddr: usize) -> // 内核的 GiB 页物理页号 let start_ppn = ((_start as usize) & GIB_MASK) >> KIB_BITS; // 内核 GiB 物理页帧在 GiB 页表中的序号 - let start_pte_index = (_start as usize) >> GIB_BITS; + 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 { - // 0x0000_0000_8000_0000 -> 0x8000_0000 - *BOOT_PAGE_TABLE.0.get_unchecked_mut(start_pte_index) = pte; - // 0xffff_ffff_8000_0000 -> 0x8000_0000 - *BOOT_PAGE_TABLE.0.get_unchecked_mut(510) = pte; + *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; + } } // 启动副核 @@ -82,6 +89,7 @@ pub extern "C" fn primary_rust_main(hartid: usize, device_tree_paddr: usize) -> } } + // 使能启动页表 let sstatus = unsafe { BOOT_PAGE_TABLE.launch(hartid) }; println!( "