Skip to content

Commit cf4675e

Browse files
committed
feat: lab0-0
1 parent 4263941 commit cf4675e

File tree

14 files changed

+408
-7
lines changed

14 files changed

+408
-7
lines changed

.gitignore

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
.DS_Store
12
.vscode
23
.idea
34
Cargo.lock
@@ -9,4 +10,6 @@ workplace/
910
os2-ref/src/link_app.S
1011
os3-ref/src/link_app.S
1112
os4-ref/src/link_app.S
12-
os5-ref/src/link_app.S
13+
os5-ref/src/link_app.S
14+
target
15+
os/target/*

os/.cargo/config

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
[build]
2+
target = "riscv64gc-unknown-none-elf"
3+
4+
5+
6+
[target.riscv64gc-unknown-none-elf]
7+
rustflags = [
8+
"-Clink-arg=-Tsrc/linker.ld", "-Cforce-frame-pointers=yes"
9+
]

os/Cargo.toml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
[package]
2+
name = "os"
3+
version = "0.1.0"
4+
edition = "2021"
5+
6+
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
7+
8+
[dependencies]
9+
log = "0.4"

os/Makefile

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
# Building
2+
TARGET := riscv64gc-unknown-none-elf
3+
MODE := release
4+
KERNEL_ELF := target/$(TARGET)/$(MODE)/os
5+
KERNEL_BIN := $(KERNEL_ELF).bin
6+
7+
# BOARD
8+
BOARD ?= qemu
9+
SBI ?= rustsbi
10+
BOOTLOADER := ../bootloader/$(SBI)-$(BOARD).bin
11+
12+
# KERNEL ENTRY
13+
KERNEL_ENTRY_PA := 0x80200000
14+
15+
# Binutils
16+
OBJDUMP := rust-objdump --arch-name=riscv64
17+
OBJCOPY := rust-objcopy --binary-architecture=riscv64
18+
19+
build: env $(KERNEL_BIN)
20+
21+
$(KERNEL_BIN): kernel
22+
@$(OBJCOPY) $(KERNEL_ELF) --strip-all -O binary $@
23+
24+
env:
25+
(rustup target list | grep "riscv64gc-unknown-none-elf (installed)") || rustup target add $(TARGET)
26+
cargo install cargo-binutils --vers ~0.2
27+
rustup component add rust-src
28+
rustup component add llvm-tools-preview
29+
30+
kernel:
31+
@cargo build --release
32+
33+
clean:
34+
@cargo clean
35+
36+
run: build
37+
@qemu-system-riscv64 \
38+
-machine virt \
39+
-nographic \
40+
-bios $(BOOTLOADER) \
41+
-device loader,file=$(KERNEL_BIN),addr=$(KERNEL_ENTRY_PA)
42+
43+
debug: build
44+
@tmux new-session -d \
45+
"qemu-system-riscv64 -machine virt -nographic -bios $(BOOTLOADER) -device loader,file=$(KERNEL_BIN),addr=$(KERNEL_ENTRY_PA) -s -S" && \
46+
tmux split-window -h "riscv64-unknown-elf-gdb -ex 'file $(KERNEL_ELF)' -ex 'set arch riscv:rv64' -ex 'target remote localhost:1234'" && \
47+
tmux -2 attach-session -d
48+
49+
.PHONY: build env kernel clean run-inner

os/src/console.rs

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
// 在main函数中
2+
use crate::console_putchar;
3+
use core::fmt::{self, Write};
4+
5+
struct Stdout;
6+
7+
impl Write for Stdout {
8+
// https://doc.rust-lang.org/core/macro.write.html
9+
fn write_str(&mut self, s: &str) -> fmt::Result {
10+
for c in s.chars() {
11+
console_putchar(c as usize);
12+
}
13+
// sys_write(1, s.as_bytes());
14+
Ok(())
15+
}
16+
}
17+
18+
pub fn print(args: fmt::Arguments) {
19+
Stdout.write_fmt(args).unwrap();
20+
}
21+
22+
#[macro_export]
23+
macro_rules! print {
24+
($fmt: literal $(, $($args: tt)+)?) => {
25+
$crate::console::print(format_args!($fmt $(, $($arg)+)?));
26+
}
27+
}
28+
29+
#[macro_export]
30+
macro_rules! println {
31+
($fmt: literal $(, $($arg: tt)+)?) => {
32+
$crate::console::print(format_args!(concat!($fmt, "\n") $(, $($arg)+)?));
33+
}
34+
}

os/src/entry.asm

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
.section .text.entry
2+
.globl _start
3+
_start:
4+
// 将SP设置为栈空间的栈顶
5+
la sp, boot_stack_top
6+
// 应用入口
7+
call rust_main
8+
9+
.section .bss.stack
10+
// 栈底
11+
.globl boot_stack
12+
13+
boot_stack:
14+
// 预留64KB,作为栈空间
15+
.space 4096 * 16
16+
// 栈顶
17+
.globl boot_stack_top
18+
19+
boot_stack_top:

os/src/lang_items.rs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
use crate::shutdown;
2+
use core::panic::PanicInfo;
3+
4+
#[panic_handler]
5+
fn panic(info: &PanicInfo) -> ! {
6+
if let Some(location) = info.location() {
7+
println!(
8+
"Panicked at {}:{} {}",
9+
location.file(),
10+
location.line(),
11+
info.message().unwrap()
12+
);
13+
} else {
14+
println!("Panicked: {}", info.message().unwrap());
15+
}
16+
shutdown()
17+
}

os/src/linker.ld

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
/* 目标平台 */
2+
OUTPUT_ARCH(riscv)
3+
/* 入口 */
4+
ENTRY(_start)
5+
/* RustSBI期望的OS起始地址 */
6+
BASE_ADDRESS = 0x80200000;
7+
8+
9+
SECTIONS
10+
{
11+
. = BASE_ADDRESS;
12+
skernel = .;
13+
14+
stext = .;
15+
/* .text代码段 */
16+
.text : {
17+
*(.text.entry)
18+
*(.text .text.*)
19+
}
20+
. = ALIGN(4K);
21+
etext = .;
22+
23+
24+
srodata = .;
25+
/* 只读数据段 */
26+
.rodata : {
27+
*(.rodata .rodata.*)
28+
}
29+
. = ALIGN(4K);
30+
erodata = .;
31+
32+
33+
sdata = .;
34+
/* 数据段 */
35+
.data : {
36+
*(.data .data.*)
37+
}
38+
. = ALIGN(4K);
39+
edata = .;
40+
41+
42+
/* bss段 */
43+
.bss : {
44+
*(.bss.stack)
45+
sbss = .;
46+
*(.bss .bss.*)
47+
}
48+
49+
. = ALIGN(4K);
50+
ebss = .;
51+
ekernel = .;
52+
53+
/DISCARD/ : {
54+
*(.eh_frame)
55+
}
56+
}

os/src/logging.rs

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
/*!
2+
3+
本模块利用 log crate 为你提供了日志功能,使用方式见 main.rs.
4+
5+
*/
6+
7+
use log::{self, Level, LevelFilter, Log, Metadata, Record};
8+
9+
struct SimpleLogger;
10+
11+
impl Log for SimpleLogger {
12+
fn enabled(&self, _metadata: &Metadata) -> bool {
13+
true
14+
}
15+
fn log(&self, record: &Record) {
16+
if !self.enabled(record.metadata()) {
17+
return;
18+
}
19+
let color = match record.level() {
20+
Level::Error => 31, // Red
21+
Level::Warn => 93, // BrightYellow
22+
Level::Info => 34, // Blue
23+
Level::Debug => 32, // Green
24+
Level::Trace => 90, // BrightBlack
25+
};
26+
println!(
27+
"\u{1B}[{}m[{:>5}] {}\u{1B}[0m",
28+
color,
29+
record.level(),
30+
record.args(),
31+
);
32+
}
33+
fn flush(&self) {}
34+
}
35+
36+
pub fn init() {
37+
static LOGGER: SimpleLogger = SimpleLogger;
38+
log::set_logger(&LOGGER).unwrap();
39+
log::set_max_level(match option_env!("LOG") {
40+
Some("ERROR") => LevelFilter::Error,
41+
Some("WARN") => LevelFilter::Warn,
42+
Some("INFO") => LevelFilter::Info,
43+
Some("DEBUG") => LevelFilter::Debug,
44+
Some("TRACE") => LevelFilter::Trace,
45+
_ => LevelFilter::Off,
46+
});
47+
}

os/src/main.rs

Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
#![no_std]
2+
#![no_main]
3+
#![feature(panic_info_message)]
4+
5+
6+
use log::*;
7+
8+
9+
#[macro_use]
10+
mod console;
11+
mod lang_items;
12+
mod logging;
13+
14+
// 使用global_asm宏将entry.asm嵌入到代码中
15+
core::arch::global_asm!(include_str!("entry.asm"));
16+
17+
18+
const SBI_SET_TIMER: usize = 0;
19+
const SBI_CONSOLE_PUTCHAR: usize = 1;
20+
const SBI_CONSOLE_GETCHAR: usize = 2;
21+
const SYSCALL_EXIT: usize = 93;
22+
const SYSCALL_WRITE: usize = 64;
23+
const SBI_SHUTDOWN: usize = 8;
24+
25+
26+
#[inline(always)]
27+
fn syscall(id: usize, args: [usize; 3]) -> usize {
28+
let mut ret;
29+
unsafe {
30+
// 应用程序访问操作系统提供的系统调用指令是ecall
31+
// 操作系统访问RustSBI提供的SBI调用指令也是ecall
32+
// 指令相同但特权级不同,应用程序处于用户级,操作系统处于内核特权级,RustSBI处于机器特权级
33+
core::arch::asm!(
34+
"ecall",
35+
inlateout("x10") args[0] => ret,
36+
in("x11") args[1],
37+
in("x12") args[2],
38+
in("x17") id,
39+
);
40+
}
41+
ret
42+
}
43+
44+
pub fn sys_exit(xstate: i32) -> usize {
45+
syscall(SYSCALL_EXIT, [xstate as usize, 0, 0])
46+
}
47+
48+
pub fn sys_write(fd: usize, buffer: &[u8]) -> usize {
49+
syscall(SYSCALL_WRITE, [fd, buffer.as_ptr() as usize, buffer.len()])
50+
}
51+
52+
pub fn console_putchar(c: usize) {
53+
syscall(SBI_CONSOLE_PUTCHAR, [c, 0, 0]);
54+
}
55+
56+
pub fn console_getchar() -> usize {
57+
syscall(SBI_CONSOLE_GETCHAR, [0, 0, 0])
58+
}
59+
60+
pub fn shutdown() -> ! {
61+
syscall(SBI_SHUTDOWN, [0, 0, 0]);
62+
panic!("It should shutdown!");
63+
}
64+
65+
fn clear_bss() {
66+
extern "C" {
67+
fn sbss();
68+
fn ebss();
69+
}
70+
(sbss as usize..ebss as usize).for_each(|a| unsafe { (a as *mut u8).write_volatile(0) });
71+
}
72+
73+
// #[no_mangle]
74+
// extern "C" fn _start() {
75+
// // loop {};
76+
// println!("Hello World");
77+
// sys_exit(9);
78+
// shutdown();
79+
// }
80+
81+
// 标记为no_mangle避免编译器对名字混淆,否则entry.asm在链接时找不到rust_main
82+
#[no_mangle]
83+
pub fn rust_main() -> ! {
84+
extern "C" {
85+
fn stext();
86+
fn etext();
87+
fn srodata();
88+
fn erodata();
89+
fn sdata();
90+
fn edata();
91+
fn sbss();
92+
fn ebss();
93+
fn boot_stack();
94+
fn boot_stack_top();
95+
}
96+
clear_bss();
97+
logging::init();
98+
println!("Hello, world!");
99+
trace!(".text [{:#x}, {:#x})", stext as usize, etext as usize);
100+
debug!(".rodata [{:#x}, {:#x})", srodata as usize, erodata as usize);
101+
info!(".data [{:#x}, {:#x})", sdata as usize, edata as usize);
102+
warn!(
103+
"boot_stack [{:#x}, {:#x})",
104+
boot_stack as usize, boot_stack_top as usize
105+
);
106+
error!(".bss [{:#x}, {:#x})", sbss as usize, ebss as usize);
107+
panic!("Shutdown machine!");
108+
// shutdown();
109+
}

0 commit comments

Comments
 (0)