初始化内核(其实就是把ch1的src复制过来)
parent
d8d5955b60
commit
4ebf1a742c
@ -0,0 +1,51 @@
|
||||
TARGET := riscv64gc-unknown-none-elf
|
||||
KERNEL_ENTRY := 0x80200000
|
||||
MODE := release
|
||||
KERNEL_ELF := target/$(TARGET)/$(MODE)/os
|
||||
KERNEL_BIN := $(KERNEL_ELF).bin
|
||||
SYMBOL_MAP := target/system.map
|
||||
QEMU_CMD_PATH := /Users/zhangxinyu/Downloads/qemu-7.0.0/build/qemu-system-riscv64
|
||||
QEMU_PID = $(shell ps aux | grep "[q]emu-system' | awk '{print $$2}")
|
||||
OBJDUMP := rust-objdump --arch-name=riscv64
|
||||
OBJCOPY := rust-objcopy --binary-architecture=riscv64
|
||||
|
||||
RUST_FLAGS := -Clink-arg=-Tsrc/linker.ld # 使用我们自己的链接脚本
|
||||
RUST_FLAGS += -Cforce-frame-pointers=yes # 强制编译器生成帧指针
|
||||
RUST_FLAGS:=$(strip ${RUST_FLAGS})
|
||||
|
||||
# 编译elf文件
|
||||
build_elf: clean
|
||||
CARGO_BUILD_RUSTFLAGS="$(RUST_FLAGS)" \
|
||||
cargo build --$(MODE) --target=$(TARGET)
|
||||
|
||||
# 导出一个符号表, 供我们查看
|
||||
$(SYMBOL_MAP):build_elf
|
||||
nm $(KERNEL_ELF) | sort > $(SYMBOL_MAP)
|
||||
|
||||
# 丢弃内核可执行elf文件中的元数据得到内核镜像
|
||||
$(KERNEL_BIN): build_elf
|
||||
@$(OBJCOPY) $(KERNEL_ELF) --strip-all -O binary $@
|
||||
|
||||
|
||||
debug:build_elf $(KERNEL_BIN) $(SYMBOL_MAP) kill
|
||||
$(QEMU_CMD_PATH) \
|
||||
-machine virt \
|
||||
-display none \
|
||||
-daemonize \
|
||||
-bios ../bootloader/rustsbi-qemu.bin \
|
||||
-device loader,file=$(KERNEL_BIN),addr=$(KERNEL_ENTRY) \
|
||||
-s -S
|
||||
|
||||
run:build_elf $(KERNEL_BIN) $(SYMBOL_MAP) kill
|
||||
$(QEMU_CMD_PATH) \
|
||||
-machine virt \
|
||||
-nographic \
|
||||
-bios ../bootloader/rustsbi-qemu.bin \
|
||||
-device loader,file=$(KERNEL_BIN),addr=$(KERNEL_ENTRY)
|
||||
|
||||
clean:
|
||||
rm -rf ./target*
|
||||
|
||||
kill:
|
||||
-kill -9 $(QEMU_PID)
|
||||
|
@ -0,0 +1,15 @@
|
||||
.section .text.entry
|
||||
.globl _start // 声明_start是全局符号
|
||||
_start:
|
||||
la sp, boot_stack_top_bound
|
||||
call rust_main
|
||||
|
||||
|
||||
|
||||
// 声明栈空间 后续 .bss.stack 会被link脚本链接到 .bss段
|
||||
.section .bss.stack
|
||||
.globl boot_stack_lower_bound // 栈低地址公开为全局符号
|
||||
.globl boot_stack_top_bound // 栈高地址公开为全局符号
|
||||
boot_stack_lower_bound:
|
||||
.space 4096 * 16
|
||||
boot_stack_top_bound:
|
@ -0,0 +1,2 @@
|
||||
pub mod panic;
|
||||
pub mod console;
|
@ -0,0 +1,33 @@
|
||||
|
||||
use crate::sbi::console_put_char;
|
||||
use core::fmt::{self, Write};
|
||||
|
||||
struct Stdout;
|
||||
|
||||
impl Write for Stdout{
|
||||
fn write_str(&mut self, s: &str) -> fmt::Result {
|
||||
for c in s.chars() {
|
||||
console_put_char(c as usize);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
// 用函数包装一下, 表示传进来的参数满足Arguments trait, 然后供宏调用
|
||||
pub fn print(args: fmt::Arguments) {
|
||||
Stdout.write_fmt(args).unwrap();
|
||||
}
|
||||
|
||||
#[macro_export] // 导入这个文件即可使用这些宏
|
||||
macro_rules! print {
|
||||
($fmt: literal $(, $($arg: tt)+)?) => {
|
||||
$crate::console::print(format_args!($fmt $(, $($arg)+)?));
|
||||
}
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! println {
|
||||
($fmt: literal $(, $($arg: tt)+)?) => {
|
||||
$crate::console::print(format_args!(concat!($fmt, "\n") $(, $($arg)+)?));
|
||||
}
|
||||
}
|
@ -0,0 +1,18 @@
|
||||
use core::panic::PanicInfo;
|
||||
use crate::println;
|
||||
use crate::sbi::shutdown;
|
||||
|
||||
#[panic_handler]
|
||||
fn panic(info: &PanicInfo) -> ! {
|
||||
if let Some(location) = info.location() {
|
||||
println!(
|
||||
"Panicked at {}:{} {}",
|
||||
location.file(),
|
||||
location.line(),
|
||||
info.message().unwrap()
|
||||
);
|
||||
} else {
|
||||
println!("Panicked: {}", info.message().unwrap());
|
||||
}
|
||||
shutdown();
|
||||
}
|
@ -0,0 +1,48 @@
|
||||
OUTPUT_ARCH(riscv) /* 目标平台 */
|
||||
ENTRY(_start) /* 设置程序入口点为entry.asm中定义的全局符号 */
|
||||
BASE_ADDRESS = 0x80200000; /* 一个常量, 我们的kernel将来加载到这个物理地址 */
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
. = BASE_ADDRESS; /* 我们对 . 进行赋值, 调整接下来的段的开始位置放在我们定义的常量出 */
|
||||
/* skernel = .;*/
|
||||
|
||||
stext = .; /* .text段的开始位置 */
|
||||
.text : { /* 表示生成一个为 .text的段, 花括号内按照防止顺序表示将输入文件中的哪些段放在 当前.text段中 */
|
||||
*(.text.entry) /* entry.asm中, 我们自己定义的.text.entry段, 被放在顶部*/
|
||||
*(.text .text.*)
|
||||
}
|
||||
|
||||
. = ALIGN(4K);
|
||||
etext = .;
|
||||
srodata = .;
|
||||
.rodata : {
|
||||
*(.rodata .rodata.*)
|
||||
*(.srodata .srodata.*)
|
||||
}
|
||||
|
||||
. = ALIGN(4K);
|
||||
erodata = .;
|
||||
sdata = .;
|
||||
.data : {
|
||||
*(.data .data.*)
|
||||
*(.sdata .sdata.*)
|
||||
}
|
||||
|
||||
. = ALIGN(4K);
|
||||
edata = .;
|
||||
.bss : {
|
||||
*(.bss.stack) /* 全局符号 sbss 和 ebss 分别指向 .bss 段除 .bss.stack 以外的起始和终止地址(.bss.stack是我们在entry.asm中定义的栈) */
|
||||
sbss = .;
|
||||
*(.bss .bss.*)
|
||||
*(.sbss .sbss.*)
|
||||
}
|
||||
|
||||
. = ALIGN(4K);
|
||||
ebss = .;
|
||||
ekernel = .;
|
||||
|
||||
/DISCARD/ : {
|
||||
*(.eh_frame)
|
||||
}
|
||||
}
|
@ -1,3 +1,41 @@
|
||||
fn main() {
|
||||
println!("Hello, world!");
|
||||
#![feature(panic_info_message)]
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
|
||||
use core::arch::global_asm;
|
||||
use sbi::{console_put_char, shutdown};
|
||||
use lang_items::console;
|
||||
|
||||
mod lang_items;
|
||||
mod sbi;
|
||||
|
||||
// 汇编脚本引入, 调整内核的内存布局之后, 会跳入到 rust_main中执行
|
||||
global_asm!(include_str!("entry.asm"));
|
||||
|
||||
extern "C" {
|
||||
fn stext();
|
||||
fn etext();
|
||||
fn sbss();
|
||||
fn ebss();
|
||||
fn boot_stack_top_bound();
|
||||
fn boot_stack_lower_bound();
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub fn rust_main(){
|
||||
init_bss();
|
||||
|
||||
println!("stext: {:#x}, etext: {:#x}", stext as usize, etext as usize);
|
||||
println!("sbss: {:#x}, ebss: {:#x}", sbss as usize, ebss as usize);
|
||||
println!("boot_stack_top_bound: {:#x}, boot_stack_lower_bound: {:#x}", boot_stack_top_bound as usize, boot_stack_lower_bound as usize);
|
||||
|
||||
panic!("my panic");
|
||||
}
|
||||
|
||||
/// ## 初始化bss段
|
||||
///
|
||||
fn init_bss() {
|
||||
unsafe {
|
||||
(sbss as usize..ebss as usize).for_each(|p| (p as *mut u8).write_unaligned(0))
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,40 @@
|
||||
use core::arch::asm;
|
||||
|
||||
// legacy extensions: ignore fid
|
||||
const SBI_SET_TIMER: usize = 0;
|
||||
const SBI_CONSOLE_PUTCHAR: usize = 1;
|
||||
const SBI_CONSOLE_GETCHAR: usize = 2;
|
||||
const SBI_CLEAR_IPI: usize = 3;
|
||||
const SBI_SEND_IPI: usize = 4;
|
||||
const SBI_REMOTE_FENCE_I: usize = 5;
|
||||
const SBI_REMOTE_SFENCE_VMA: usize = 6;
|
||||
const SBI_REMOTE_SFENCE_VMA_ASID: usize = 7;
|
||||
|
||||
// system reset extension
|
||||
const SRST_EXTENSION: usize = 0x53525354;
|
||||
const SBI_SHUTDOWN: usize = 0;
|
||||
|
||||
#[inline(always)]
|
||||
fn sbi_call(eid: usize, fid: usize, arg0: usize, arg1: usize, arg2: usize) -> usize {
|
||||
let mut ret;
|
||||
unsafe {
|
||||
asm!(
|
||||
"ecall",
|
||||
inlateout("x10") arg0 => ret,
|
||||
in("x11") arg1,
|
||||
in("x12") arg2,
|
||||
in("x16") fid,
|
||||
in("x17") eid,
|
||||
);
|
||||
}
|
||||
ret
|
||||
}
|
||||
|
||||
pub fn console_put_char(c: usize) {
|
||||
sbi_call(SBI_CONSOLE_PUTCHAR, 0, c, 0, 0);
|
||||
}
|
||||
|
||||
pub fn shutdown() -> ! {
|
||||
sbi_call(SRST_EXTENSION, SBI_SHUTDOWN, 0, 0, 0);
|
||||
panic!("It should shutdown!")
|
||||
}
|
Loading…
Reference in New Issue