diff --git a/ch1/Cargo.toml b/ch1/Cargo.toml index 60b4d6d..ee13f12 100644 --- a/ch1/Cargo.toml +++ b/ch1/Cargo.toml @@ -6,3 +6,8 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] + + +# 设置release模式下保存调试信息 +[profile.release] +debug=true \ No newline at end of file diff --git a/ch1/Makefile b/ch1/Makefile index 312c6ba..adb85bb 100644 --- a/ch1/Makefile +++ b/ch1/Makefile @@ -1,10 +1,11 @@ - 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 @@ -13,24 +14,38 @@ RUST_FLAGS += -Cforce-frame-pointers=yes # 强制编译器生成帧指针 RUST_FLAGS:=$(strip ${RUST_FLAGS}) # 编译elf文件 -build: +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 +$(KERNEL_BIN): build_elf @$(OBJCOPY) $(KERNEL_ELF) --strip-all -O binary $@ -run:build $(KERNEL_BIN) +debug:build_elf $(KERNEL_BIN) $(SYMBOL_MAP) kill $(QEMU_CMD_PATH) \ -machine virt \ - -nographic \ + -display none \ + -daemonize \ -bios ../bootloader/rustsbi-qemu.bin \ - -device loader,file=$(KERNEL_ELF),addr=$(KERNEL_ENTRY) \ + -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 \ No newline at end of file + rm -rf ./target* + +kill: + -kill -9 $(QEMU_PID) + diff --git a/ch1/src/entry.asm b/ch1/src/entry.asm index 0737fbf..cd24d76 100644 --- a/ch1/src/entry.asm +++ b/ch1/src/entry.asm @@ -1,5 +1,15 @@ .section .text.entry .globl _start // 声明_start是全局符号 _start: - li x1, 100 + la sp, boot_stack_top + call rust_main + + +// 声明栈空间 后续 .bss.stack 会被link脚本链接到 .bss段 + .section .bss.stack + .globl boot_stack_lower_bound // 栈低地址公开为全局符号 + .globl boot_stack_top // 栈高地址公开为全局符号 +boot_stack_lower_bound: + .space 4096 * 16 +boot_stack_top: diff --git a/ch1/src/lang_items.rs b/ch1/src/lang_items.rs index 3d5f71b..53e74c5 100644 --- a/ch1/src/lang_items.rs +++ b/ch1/src/lang_items.rs @@ -1 +1,2 @@ -pub mod panic; \ No newline at end of file +pub mod panic; +pub mod console; \ No newline at end of file diff --git a/ch1/src/lang_items/console.rs b/ch1/src/lang_items/console.rs new file mode 100644 index 0000000..e4330a1 --- /dev/null +++ b/ch1/src/lang_items/console.rs @@ -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)+)?)); + } +} diff --git a/ch1/src/lang_items/panic.rs b/ch1/src/lang_items/panic.rs index fac89de..58dde79 100644 --- a/ch1/src/lang_items/panic.rs +++ b/ch1/src/lang_items/panic.rs @@ -1,8 +1,21 @@ - - use core::panic::PanicInfo; +use crate::println; +use crate::sbi::shutdown; #[panic_handler] -fn panic(_info: &PanicInfo) -> ! { - loop {} +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(); + loop { + + } } \ No newline at end of file diff --git a/ch1/src/linker.ld b/ch1/src/linker.ld index 7fb5178..099fd87 100644 --- a/ch1/src/linker.ld +++ b/ch1/src/linker.ld @@ -32,7 +32,7 @@ SECTIONS . = ALIGN(4K); edata = .; .bss : { - *(.bss.stack) + *(.bss.stack) /* 全局符号 sbss 和 ebss 分别指向 .bss 段除 .bss.stack 以外的起始和终止地址(.bss.stack是我们在entry.asm中定义的栈) */ sbss = .; *(.bss .bss.*) *(.sbss .sbss.*) diff --git a/ch1/src/main.rs b/ch1/src/main.rs index e883f38..c5087fc 100644 --- a/ch1/src/main.rs +++ b/ch1/src/main.rs @@ -1,11 +1,39 @@ +#![feature(panic_info_message)] #![no_std] #![no_main] -mod lang_items; 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")); -// fn main() { -// -// // println!("Hello, world!"); -// } + + +#[no_mangle] +pub fn rust_main(){ + init_bss(); + println!("hello world"); + + let mut a = 123; + a = 234; + a = 345; + println!("hello world {:?}", a); + + panic!("my panic"); +} + +/// ## 初始化bss段 +/// +fn init_bss() { + extern "C" { + static mut sbss: u64; + static mut ebss: u64; + } + unsafe { + (sbss..ebss).for_each(|p| (p as *mut u8).write_unaligned(0)) + } +} diff --git a/ch1/src/sbi.rs b/ch1/src/sbi.rs new file mode 100644 index 0000000..e954239 --- /dev/null +++ b/ch1/src/sbi.rs @@ -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!") +} \ No newline at end of file