Merge pull request #280 from YdrMaster/dev-boot-riscv

整理 riscv 启动逻辑,并为汇编增加注释
This commit is contained in:
Luoyuan Xiao 2022-04-22 17:00:12 +08:00 committed by GitHub
commit 5741f12e5f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 209 additions and 185 deletions

13
.gitignore vendored
View File

@ -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__

View File

@ -1 +0,0 @@
nightly-2022-01-20

4
rust-toolchain.toml Normal file
View File

@ -0,0 +1,4 @@
[toolchain]
channel = "nightly-2022-01-20"
components = ["rust-src", "llvm-tools-preview", "rustfmt", "clippy"]
targets = ["riscv64gc-unknown-none-elf"]

View File

@ -2,7 +2,7 @@
name = "zcore"
version = "0.1.0"
authors = ["PanQL <panqinglin00@163.com>", "Yuekai Jia <equation618@gmail.com>"]
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 }

View File

@ -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.

View File

@ -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

View File

@ -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
#5100
.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

View File

@ -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
#12satp的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:

View File

@ -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 = .);
}

View File

@ -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::<usize>();
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
}
}