forked from rcore-os/zCore
Merge pull request #280 from YdrMaster/dev-boot-riscv
整理 riscv 启动逻辑,并为汇编增加注释
This commit is contained in:
commit
5741f12e5f
|
|
@ -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__
|
||||
|
|
|
|||
|
|
@ -1 +0,0 @@
|
|||
nightly-2022-01-20
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
[toolchain]
|
||||
channel = "nightly-2022-01-20"
|
||||
components = ["rust-src", "llvm-tools-preview", "rustfmt", "clippy"]
|
||||
targets = ["riscv64gc-unknown-none-elf"]
|
||||
|
|
@ -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 }
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
@ -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
|
||||
|
||||
|
|
@ -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:
|
||||
|
||||
|
|
|
|||
|
|
@ -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 = .);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue