Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
165 changes: 164 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,172 @@
# 欢迎来到Tcore

Tcore是基于rust编写的可在qemu和真实硬件平台上运行的64位操作系统,在开发的过程中我们学习和解决了一系列问题现在将主要问题和解决办法分列如下。在此之前特别致谢吴一凡提供的精美rcore-tutorial-v3以及他本人在开发过程中的答疑和哈工深Ultraos的支持。

## 比赛准备和调研

首先是我们期待达到的目标,即可以展示SPDK的线程模型的教学操作系统。Tcore的设计是我们一次在不确定中寻找确定性的一次尝试,在os的比赛过程中我们看到了无数前人的探索,留下的成果可谓是硕果累累,也是为后人学习和交流留下的宝贵资源。我们的探索是艰难但是有意义的,对于我们这个没有os实训平台的学校来说我们希望通过努力将os的一些新的教学成果引入到同学们的学习和探究中来。在学习的过程中我们深感os的复杂和精妙但是每一次新知识的获取和驾驭都使得我们为之兴奋。我们将前期准备分列如下。

+ 前期对于os概念的学习
我们在开发中整理了rcore-tutorial-book-v3相关的概念形成了约八万字的文档同时进行了一些流程图和概念图的梳理便于我们开发查阅以及为后续继续完善和学习的同学留下快速上手的资料。文档地址如下:https://shimo.im/docs/KlkKVy55PBTwreqd
+ SPDK线程模型的引进
这是我们在接触到目前分布式云存储发展火热的情况下SPDK的运用也更加的普遍我们也希望在开发的过程中能够吸收一些概念在教学实践中让同学们能够快速上手os的同时也能了解目前一些成熟技术栈。对此我们进行了许多尝试包括直接引进SPDK的rust绑定仓库地址如下:https://github.com/openebs/spdk-sys.git
他会将spdk仓库也直接同步过来但是我们发现他过于庞大于是我们聚焦在多核的线程模型也是SPDK设计的核心——————无锁化编程。由于我们的初赛的时间有限目前仅仅完成了线程抽象,SPDK模型还在改进中。
文档地址:https://www.daimajiaoliu.com/daima/8c76677d954e802
+ 由于SPDK线程模型的需要我们需要在多核基础上实现于是我们在去年哈工深Ultraos上进行学习和大量改动在此之前学习了解他的文档和主要的设计思路以便于我们快速上手和学习。这里特别感谢李程浩团队的作品和他本人对于前期开发给与的帮助。再次感谢。

## 系统设计和模块设计

+ 地址空间mm模块memory_set相关函数的改写
+ 线程改进task模块的重写
+ trap模块的重写
+ 其他包括为通过初赛样例的makefile调整和便于使用的user_shell的调整
+ config模块参数的重写设计
+ 整体的模块设计如图所示

## 致谢吴一凡大佬的rcore-tutorial-v3和哈工大深圳冠军队伍UltraOs的支持
![内核模块示意](docs/images/内核模块示意.png)

## 开发计划

+ 初赛阶段对于通过测试样例改进了许多东西也成功完成了线程抽象
+ 复赛期间完成SPDK模型改进以及编写更加便于学习理解的文档教程
![spdk线程示意](docs/images/spdk线程模型.png)

## 遇到的主要问题和解决办法

+ 由于线程共享地址空间于是将原来的配置文件和地址空间布局进行了改写目前地址空间布局如下:

![地址空间](docs/images/地址空间.png)

+ trap相关处理重写了trap模块使得内核栈和用户栈平滑过渡。相关代码如下:

```asm
.altmacro
.macro SAVE_GP n
sd x\n, \n*8(sp)
.endm
.macro LOAD_GP n
ld x\n, \n*8(sp)
.endm
.section .text.trampoline
.globl __alltraps
.globl __restore
.align 2
__alltraps:
csrrw sp, sscratch, sp
# now sp->*TrapContext in user space, sscratch->user stack
# save other general purpose registers
sd x1, 1*8(sp)
# skip sp(x2), we will save it later
sd x3, 3*8(sp)
# skip tp(x4), application does not use it
# save x5~x31
.set n, 5
.rept 27
SAVE_GP %n
.set n, n+1
.endr
# we can use t0/t1/t2 freely, because they have been saved in TrapContext
csrr t0, sstatus
csrr t1, sepc
sd t0, 32*8(sp)
sd t1, 33*8(sp)
# read user stack from sscratch and save it in TrapContext
csrr t2, sscratch
sd t2, 2*8(sp)
# load kernel_satp into t0
ld t0, 34*8(sp)
# load trap_handler into t1
ld t1, 36*8(sp)
# move to kernel_sp
ld sp, 35*8(sp)
# switch to kernel space
csrw satp, t0
sfence.vma
# jump to trap_handler
jr t1

__restore:
# a0: *TrapContext in user space(Constant); a1: user space token
# switch to user space
csrw satp, a1
sfence.vma
csrw sscratch, a0
mv sp, a0
# now sp points to TrapContext in user space, start restoring based on it
# restore sstatus/sepc
ld t0, 32*8(sp)
ld t1, 33*8(sp)
csrw sstatus, t0
csrw sepc, t1
# restore general purpose registers except x0/sp/tp
ld x1, 1*8(sp)
ld x3, 3*8(sp)
.set n, 5
.rept 27
LOAD_GP %n
.set n, n+1
.endr
# back to user stack
ld sp, 2*8(sp)
sret

## 开发计划
+ 初赛阶段对于通过测试样例改进了许多东西也成功完成了线程抽象
+ 复赛期间完成SPDK模型改进以及编写更加便于学习理解的文档教程
![spdk线程示意](docs/images/spdk线程模型.png)

## 遇到的主要问题和解决办法
+ 由于线程共享地址空间于是将原来的配置文件和地址空间布局进行了改写目前地址空间布局如下:


```

汇编逻辑如下:

![trap逻辑](docs/images/trap示意.png)

+ 初始进程的添加以及新的进程调用调用的问题,将PCB包裹在Arc<Mutex<>>模块更安全的用于多核线程初始化代码如下

```rust
pub struct ProcessControlBlock {
//immutable
pub pid: PidHandle,
//mutable
inner: Arc<Mutex<ProcessControlBlockInner>>,
}
```

为了便于清晰理解这个过程我们绘制了以下的流程图:

![进程新建示意](docs/images/进程新建过程.png)

+ Tcore开机流程示意

![开机加载](docs/images/起电.png)

## 作品特征描述

Tcore目前是能够稳定在双核qemu虚拟机或者k210板上运行,同时在processor文件处理好的情况下更换新的sbi后理论上可以在4核平台上运行。复赛阶段有余力的话我们会进行拓展,同时也交流学习到了一些多核故障的处理。同时我们继承了前辈优秀的FAT32文件系统。目前Tcore文档的支持是相当丰富的我们同时也在仓库中放置了一些整理的文档,结合上文在前期调研的一些文档我们希望能够同学们快速上手,享受到目前国内大学生对于操作系统探索的一些成果!同时在此模块中我们将大赛开发中几个好用的工具也一便放置于此。

+ 绘制白板:https://ajietextd.github.io/
+ 流程图绘制 :推荐ProcessOn
+ GDB调试面板DashBoard:https://github.com/cyrus-and/gdb-dashboard 网速不好的情况下可以直击复制在自己工作目录下使用(保持文件名相同复制.gdbinit文件内容)
+ GDB常见命令:https://mp.weixin.qq.com/s/XxPIfrQ3E0GR88UsmQNggg

## 分工和协作

+ 王炼(队长):负责task模块的重写和trap的设计
+ 王涛(队员): 负责样例测试以及task模块的设计
+ 陈钰霖(队员 ): 负责文档整理以及shell设计和解决task一些bug

## 仓库文件阅读提示

+ codes/os:放置内核代码
+ codes/dependency:为稳定支持inline_asm指定的本地库以及其他依赖经过我们的研究测试可以支持llvm_asm!和asm!
+ codes/fat32 :构建文件系统
+ codes/user:用户程序
+ docs :相关文档以及相关插图

## 比赛收获

本次大赛我们是从去年开始学习rust语言和操作系统相关知识,在本次大赛报名之后我们确立了开发的方向和要创新的地方。我们所处的地区因为疫情也使得开发过程出现了一些困难。但是在整个过程中我们前后迭代代码逾四千多行在开发中不断学习也写下了许多文档,最为重要的收获是在这个过程中许多同学的无私帮忙以及指导老师梁琨老师的进度追踪也在不断的解决报错中深入理解了OS的概念坚定了我们复赛的信念。同时我们也希望将这样的精神和知识传递下去争取在我们学校的教学过程中也引入相关的OS实训平台。
Binary file added TCore文档.pdf
Binary file not shown.
6 changes: 6 additions & 0 deletions codes/os/.cargo/config
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,9 @@ target = "riscv64imac-unknown-none-elf"
rustflags = [
"-Clink-arg=-Tsrc/linker.ld", "-Cforce-frame-pointers=yes" , "-g"
]

[source.crates-io]
replace-with = "vendored-sources"

[source.vendored-sources]
directory = "vendor"
2 changes: 1 addition & 1 deletion codes/os/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[package]
name = "tCore"
name = "os"
version = "0.1.1"
authors = ["LoanCold <[email protected]>", "Haochen Gong <[email protected]>", "Xiangyu REN"]
edition = "2018"
Expand Down
17 changes: 8 additions & 9 deletions codes/os/Makefile
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# Building
TARGET := riscv64imac-unknown-none-elf
MODE := release
KERNEL_ELF := target/$(TARGET)/$(MODE)/tCore
KERNEL_ELF := target/$(TARGET)/$(MODE)/os
KERNEL_BIN := $(KERNEL_ELF).bin
DISASM_TMP := target/$(TARGET)/$(MODE)/asm
FS_IMG := ../user/target/$(TARGET)/$(MODE)/fs.img
Expand All @@ -16,7 +16,7 @@ endif

SDCARD := /dev/sdb
APPS := ../user/src/bin/*
TOP := ../../k210.bin
TOP := ../../os.bin

# BOARD
BOARD ?= qemu
Expand Down Expand Up @@ -49,7 +49,7 @@ OBJCOPY := rust-objcopy --binary-architecture=riscv64
DISASM ?= -x

# build: env $(KERNEL_BIN) $(FS_IMG) fat32
build: $(KERNEL_BIN)
build: env $(KERNEL_BIN)

env:
rustup override set nightly-2021-05-10
Expand Down Expand Up @@ -82,7 +82,7 @@ fsimg-format:
kernel:
@echo Platform: $(BOARD)
@cp src/linker-$(BOARD).ld src/linker.ld
@cargo build --release --features "board_$(BOARD)"
@cargo build --offline --release --features "board_$(BOARD)"
@rm src/linker.ld

clean:
Expand Down Expand Up @@ -112,15 +112,14 @@ endif


monitor:
riscv64-unknown-elf-gdb -ex 'file target/riscv64imac-unknown-none-elf/release/tCore' -ex 'set arch riscv:rv64' -ex 'target remote localhost:1234'
riscv64-unknown-elf-gdb -ex 'file target/riscv64imac-unknown-none-elf/release/os' -ex 'set arch riscv:rv64' -ex 'target remote localhost:1234'

gdb: build
@qemu-system-riscv64 -machine virt -nographic -bios ../bootloader/rustsbi-qemu.bin -device loader,\
file=target/riscv64imac-unknown-none-elf/release/tCore,addr=0x80200000 -drive \
gdb:
@qemu-system-riscv64 -machine virt -nographic -bios $(BOOTLOADER) -device loader,\
file=target/riscv64imac-unknown-none-elf/release/os,addr=0x80200000 -drive \
file=$(U_FAT32),if=none,format=raw,id=x0 \
-device virtio-blk-device,drive=x0,bus=virtio-mmio-bus.0 -smp threads=2 -S -s


runsimple:
@qemu-system-riscv64 \
-machine virt \
Expand Down
45 changes: 14 additions & 31 deletions codes/os/src/console.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,18 @@
use core::fmt::{self, Write};
use crate::sbi::console_putchar;
use core::fmt::{self, Write};
use spin::Mutex;

struct Stdout;

pub struct ConsoleInner;

impl ConsoleInner {
fn puts(&self, args: fmt::Arguments) {
Stdout.write_fmt(args).unwrap();
}
}

static CONSOLE: Mutex<ConsoleInner> = Mutex::new(ConsoleInner {});

impl Write for Stdout {
fn write_str(&mut self, s: &str) -> fmt::Result {
Expand All @@ -14,46 +24,19 @@ impl Write for Stdout {
}

pub fn print(args: fmt::Arguments) {
Stdout.write_fmt(args).unwrap();
CONSOLE.lock().puts(args);
}



//#[cfg(feature = "board_qemu")]
#[macro_export]
macro_rules! print {
($fmt: literal $(, $($arg: tt)+)?) => {
$crate::console::print(format_args!($fmt $(, $($arg)+)?));
//$crate::fs::_print(format_args!($fmt $(, $($arg)+)?));
$crate::console::print(format_args!($fmt $(, $($arg)+)?))
}
}

//#[cfg(feature = "board_qemu")]
#[macro_export]
macro_rules! println {
($fmt: literal $(, $($arg: tt)+)?) => {
$crate::console::print(format_args!(concat!($fmt, "\n") $(, $($arg)+)?));
//$crate::fs::_print(format_args!(core::concat!($fmt, "\n") $(, $($arg)+)?));
$crate::console::print(format_args!(concat!($fmt, "\n") $(, $($arg)+)?))
}
}

/*
#[cfg(feature = "board_k210")]
#[macro_export]
macro_rules! print {
($fmt: literal $(, $($arg: tt)+)?) => {
$crate::console::print(format_args!($fmt $(, $($arg)+)?));
//$crate::fs::_print(format_args!($fmt $(, $($arg)+)?));
}
}

#[cfg(feature = "board_k210")]
#[macro_export]
macro_rules! println {
($fmt: literal $(, $($arg: tt)+)?) => {
$crate::console::print(format_args!(concat!($fmt, "\n") $(, $($arg)+)?));
//$crate::fs::_print(format_args!(core::concat!($fmt, "\n") $(, $($arg)+)?));
}
}*/


6 changes: 3 additions & 3 deletions codes/os/src/fs/inode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -405,9 +405,9 @@ bitflags! {
const RDWR = 1 << 1;
const CREATE = 1 << 6;
const TRUNC = 1 << 10;
const DIRECTROY = 0200000;
const LARGEFILE = 0100000;
const CLOEXEC = 02000000;
const DIRECTROY = 0x200000;
const LARGEFILE = 0x100000;
const CLOEXEC = 0x2000000;
}
}

Expand Down
20 changes: 10 additions & 10 deletions codes/os/src/syscall/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -181,12 +181,12 @@ pub fn syscall(syscall_id: usize, args: [usize; 6]) -> isize {
SYSCALL_YIELD => sys_yield(),
SYSCALL_KILL => sys_kill(args[0], args[1] as u32),
//SYSCALL_SIGACTION => sys_sigaction(args[0] as isize, args[1] as *mut usize, args[2] as *mut usize),
// SYSCALL_TIMES => sys_times(args[0] as *mut i64),
SYSCALL_TIMES => sys_times(args[0] as *mut i64),
SYSCALL_UNAME => sys_uname(args[0] as *mut u8),
// SYSCALL_GETRUSAGE => sys_getrusage(args[0] as isize, args[1] as *mut u8),
SYSCALL_GET_TIME_OF_DAY => sys_get_time_of_day(args[0] as *mut u64),
//SYSCALL_SBRK => sys_sbrk(args[0] as isize, args[1] as usize),
//SYSCALL_BRK => sys_brk(args[0]),
SYSCALL_BRK => sys_brk(args[0]),

SYSCALL_GETPID => sys_getpid(),
SYSCALL_GETPPID => sys_getppid(),
Expand All @@ -203,28 +203,28 @@ pub fn syscall(syscall_id: usize, args: [usize; 6]) -> isize {
unsafe {
//llvm_asm!("sfence.vma" :::: "volatile");
}
sys_fork()
sys_fork(args[0] as usize, args[1] as usize, args[2] as usize, args[3] as usize, args[4] as usize)
},
SYSCALL_EXEC => {
unsafe {
//llvm_asm!("sfence.vma" :::: "volatile");
}
sys_exec(args[0] as *const u8, args[1] as *const usize)
},
// SYSCALL_WAIT4 => {
// unsafe {
// //llvm_asm!("sfence.vma" :::: "volatile");
// }
// sys_wait4(args[0] as isize, args[1] as *mut i32, args[2] as isize)
// },
SYSCALL_WAIT4 => {
// unsafe {
// //llvm_asm!("sfence.vma" :::: "volatile");
// }
sys_wait4(args[0] as isize, args[1] as *mut i32, args[2] as isize)
},
SYSCALL_PRLIMIT => 0,

SYSCALL_RENAMEAT2 => sys_renameat2(
args[0] as isize, args[1] as *const u8,
args[2] as isize, args[3] as *const u8, args[4] as u32
),

// SYSCALL_WAITPID => sys_waitpid(args[0] as isize, args[1] as *mut i32),
SYSCALL_WAITPID => sys_waitpid(args[0] as isize, args[1] as *mut i32),
SYSCALL_MMAP => {
unsafe {
//llvm_asm!("sfence.vma" :::: "volatile");
Expand Down
Loading