Skip to content

Commit

Permalink
0.2.0 print from app
Browse files Browse the repository at this point in the history
  • Loading branch information
buhe committed Sep 30, 2021
1 parent 3ece318 commit 1065854
Show file tree
Hide file tree
Showing 21 changed files with 246 additions and 24 deletions.
4 changes: 4 additions & 0 deletions docs/1 提纲.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@
- 可以更好的了解计算机的技术,知其所以然。如异步 IO ,在了解了操作系统之后就可以知道为什么快了。
- 在面试的时候可以回答的更深入。如考官再问从用户点击网址到浏览器渲染都经历什么?结合操作系统知识就可以回答的更好。

### 操作系统的分类

- 微内核和宏内核

### 硬件

我们使用 k210 来实验,我买的这个 https://world.taobao.com/item/598263769069.htm k210 maix bit ,目前没有屏幕和 wifi ,因为现在还用不上,以后会加上的。
Expand Down
15 changes: 13 additions & 2 deletions docs/3 打印.md
Original file line number Diff line number Diff line change
Expand Up @@ -121,8 +121,19 @@ hello OS

### 后续

1. 全局位初始化变量清零
2. panic 打印位置
- 全局位初始化变量清零

```rust
fn clear_bss() {
extern "C" {
fn sbss();
fn ebss();
}
(sbss as usize..ebss as usize).for_each(|a| {
unsafe { (a as *mut u8).write_volatile(0) }
});
}
```

### 额外加餐 打印五彩斑斓的调试日志

4 changes: 2 additions & 2 deletions docs/4 虚拟化 CPU 特权.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
### 特权级

目标是这次也打印 Hello OS 不同的是,在用户态
目标是这次也打印 Hello OS 不同的是,在用户态运行的应用

背景是,试想一个应用就能破坏操作系统,操作系统多脆弱啊。应用有意无意的错误不要影响到操作系统和其他应用,这就需要硬件和操作系统配合来提供特权。应用只能运行在用户态,这样应用就可以放心使用 CPU ,这是 CPU 第一种虚拟化。
为什么需要系统调用?特权?trap?CPU 虚拟化?直接都给权限,都在一个态不香么?试想一个应用就能破坏操作系统,操作系统多脆弱啊。应用有意无意的错误不要影响到操作系统和其他应用,这就需要硬件和操作系统配合来提供特权。应用只能运行在用户态,这样应用就可以放心使用 CPU ,这是 CPU 第一种虚拟化。

应用在用户态,操作系统在内核态。应用不能自己执行危险操作,想要执行必须通过系统调用委托给操作系统,而我们信赖操作系统。今天我们尝试在 k210 上实现特权级。

Expand Down
File renamed without changes.
File renamed without changes.
Empty file.
File renamed without changes.
56 changes: 56 additions & 0 deletions os/build.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
use std::fs::{read_dir, File};
use std::io::{Result, Write};

fn main() {
println!("cargo:rerun-if-changed=../user/src/");
println!("cargo:rerun-if-changed={}", TARGET_PATH);
insert_app_data().unwrap();
}

static TARGET_PATH: &str = "../user/target/riscv64gc-unknown-none-elf/release/";

fn insert_app_data() -> Result<()> {
let mut f = File::create("src/link_app.S").unwrap();
let mut apps: Vec<_> = read_dir("../user/src/bin")
.unwrap()
.into_iter()
.map(|dir_entry| {
let mut name_with_ext = dir_entry.unwrap().file_name().into_string().unwrap();
name_with_ext.drain(name_with_ext.find('.').unwrap()..name_with_ext.len());
name_with_ext
})
.collect();
apps.sort();

writeln!(
f,
r#"
.align 3
.section .data
.global _num_app
_num_app:
.quad {}"#,
apps.len()
)?;

for i in 0..apps.len() {
writeln!(f, r#" .quad app_{}_start"#, i)?;
}
writeln!(f, r#" .quad app_{}_end"#, apps.len() - 1)?;

for (idx, app) in apps.iter().enumerate() {
println!("app_{}: {}", idx, app);
writeln!(
f,
r#"
.section .data
.global app_{0}_start
.global app_{0}_end
app_{0}_start:
.incbin "{2}{1}.bin"
app_{0}_end:"#,
idx, app, TARGET_PATH
)?;
}
Ok(())
}
4 changes: 3 additions & 1 deletion os/src/lang.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
use core::panic::PanicInfo;

use crate::scall_sbi::shutdown;

#[panic_handler]
fn panic(_: &PanicInfo) -> ! {
loop {}
shutdown();
}
15 changes: 15 additions & 0 deletions os/src/link_app.S
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@

.align 3
.section .data
.global _num_app
_num_app:
.quad 1
.quad app_0_start
.quad app_0_end

.section .data
.global app_0_start
.global app_0_end
app_0_start:
.incbin "../user/target/riscv64gc-unknown-none-elf/release/hello.bin"
app_0_end:
16 changes: 13 additions & 3 deletions os/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,28 @@
#![no_std]
#![no_main]

use scall_sbi::shutdown;
#[macro_use]
mod console;
mod lang;
mod scall_sbi;
mod task;
mod trap;

global_asm!(include_str!("stack.asm"));
global_asm!(include_str!("link_app.S"));

fn clear_bss() {
extern "C" {
fn sbss();
fn ebss();
}
(sbss as usize..ebss as usize).for_each(|a| unsafe { (a as *mut u8).write_volatile(0) });
}

#[no_mangle]
extern "C" fn rust_main() -> ! {
println!("hello OS");
clear_bss();
trap::init();
shutdown();
task::init();
task::run();
}
4 changes: 2 additions & 2 deletions os/src/scall_sbi/fs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@ pub fn sys_write(fd: usize, buf: *const u8, len: usize) -> isize {
let str = core::str::from_utf8(slice).unwrap();
print!("{}", str);
len as isize
},
}
_ => {
panic!("Unsupported fd in sys_write!");
}
}
}
}
4 changes: 2 additions & 2 deletions os/src/scall_sbi/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ fn scall(which: usize, arg0: usize, arg1: usize, arg2: usize) -> usize {
in ("x12") arg2,
in("x17") which,
lateout("x10") ret,
options(nostack)
);
}
ret
Expand All @@ -24,7 +25,6 @@ pub fn put_char(c: usize) {
scall(SBI_CONSOLE_PUTCHAR, c, 0, 0);
}


const SYSCALL_WRITE: usize = 64;
const SYSCALL_EXIT: usize = 93;

Expand All @@ -40,4 +40,4 @@ pub fn syscall(syscall_id: usize, args: [usize; 3]) -> isize {
SYSCALL_EXIT => sys_exit(args[0] as i32),
_ => panic!("Unsupported syscall_id: {}", syscall_id),
}
}
}
2 changes: 1 addition & 1 deletion os/src/scall_sbi/process.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
pub fn sys_exit(exit_code: i32) -> ! {
println!("[kernel] Application exited with code {}", exit_code);
panic!("It should shutdown!");
}
}
115 changes: 115 additions & 0 deletions os/src/task/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
use crate::trap::TrapContext;
use core::{cell::RefCell, usize};
use lazy_static::*;

const USER_STACK_SIZE: usize = 4096 * 2;
const KERNEL_STACK_SIZE: usize = 4096 * 2;
const APP_BASE_ADDRESS: usize = 0x80400000;
const APP_SIZE_LIMIT: usize = 0x20000;

#[repr(align(4096))]
struct KernelStack {
data: [u8; KERNEL_STACK_SIZE],
}

#[repr(align(4096))]
struct UserStack {
data: [u8; USER_STACK_SIZE],
}

static KERNEL_STACK: KernelStack = KernelStack {
data: [0; KERNEL_STACK_SIZE],
};
static USER_STACK: UserStack = UserStack {
data: [0; USER_STACK_SIZE],
};

impl KernelStack {
fn get_sp(&self) -> usize {
self.data.as_ptr() as usize + KERNEL_STACK_SIZE
}
pub fn push_context(&self, cx: TrapContext) -> &'static mut TrapContext {
let cx_ptr = (self.get_sp() - core::mem::size_of::<TrapContext>()) as *mut TrapContext;
unsafe {
*cx_ptr = cx;
}
unsafe { cx_ptr.as_mut().unwrap() }
}
}

impl UserStack {
fn get_sp(&self) -> usize {
self.data.as_ptr() as usize + USER_STACK_SIZE
}
}

struct AppManager {
inner: RefCell<AppManagerInner>,
}
struct AppManagerInner {
app_start: [usize; 2],
}
unsafe impl Sync for AppManager {}

impl AppManagerInner {
pub fn print_app_info(&self) {
println!(
"[kernel] app_{} [{:#x}, {:#x})",
0, self.app_start[0], self.app_start[1]
);
}

unsafe fn load_app(&self) {
// clear app area
(APP_BASE_ADDRESS..APP_BASE_ADDRESS + APP_SIZE_LIMIT).for_each(|addr| {
(addr as *mut u8).write_volatile(0);
});
let app_src = core::slice::from_raw_parts(
self.app_start[0] as *const u8,
self.app_start[1] - self.app_start[0],
);
let app_dst = core::slice::from_raw_parts_mut(APP_BASE_ADDRESS as *mut u8, app_src.len());
app_dst.copy_from_slice(app_src);
}
}

lazy_static! {
static ref APP_MANAGER: AppManager = AppManager {
inner: RefCell::new({
extern "C" {
fn _num_app();
}
let num_app_ptr = _num_app as usize as *const usize;
let num_app = unsafe { num_app_ptr.read_volatile() };
let mut app_start: [usize; 2] = [0; 2];
let app_start_raw: &[usize] =
unsafe { core::slice::from_raw_parts(num_app_ptr.add(1), num_app + 1) };
app_start[..=num_app].copy_from_slice(app_start_raw);
AppManagerInner { app_start }
}),
};
}

pub fn init() {
print_app_info();
}

pub fn print_app_info() {
APP_MANAGER.inner.borrow().print_app_info();
}

pub fn run() -> ! {
unsafe {
APP_MANAGER.inner.borrow().load_app();
}
extern "C" {
fn __restore(cx_addr: usize);
}
unsafe {
__restore(KERNEL_STACK.push_context(TrapContext::app_init_context(
APP_BASE_ADDRESS,
USER_STACK.get_sp(),
)) as *const _ as usize);
}
panic!("Unreachable in task::run!");
}
18 changes: 9 additions & 9 deletions os/src/trap/mod.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
use riscv::register::{scause::{self, Exception, Trap}, stval, stvec, utvec::TrapMode};
use trap_ctx::TrapContext;
use riscv::register::{
scause::{self, Exception, Trap},
stval, stvec,
utvec::TrapMode,
};
pub use trap_ctx::TrapContext;

use crate::scall_sbi::syscall;

mod trap_ctx;
global_asm!(include_str!("trap.asm"));
global_asm!(include_str!("trap.S"));

pub fn init() {
extern "C" {
Expand All @@ -26,15 +30,11 @@ pub fn trap_handler(cx: &mut TrapContext) -> &mut TrapContext {
}
Trap::Exception(Exception::StoreFault) | Trap::Exception(Exception::StorePageFault) => {
println!("[kernel] PageFault in application, core dumped.");
panic!(
"StoreFault!"
);
panic!("StoreFault!");
}
Trap::Exception(Exception::IllegalInstruction) => {
println!("[kernel] IllegalInstruction in application, core dumped.");
panic!(
"IllegalInstruction!"
);
panic!("IllegalInstruction!");
}
_ => {
panic!(
Expand Down
File renamed without changes.
8 changes: 8 additions & 0 deletions user/.cargo/config
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
[build]
target = "riscv64gc-unknown-none-elf"


[target.riscv64gc-unknown-none-elf]
rustflags = [
"-Clink-arg=-Tsrc/linker.ld", "-Cforce-frame-pointers=yes"
]
2 changes: 1 addition & 1 deletion user/src/bin/hello.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,6 @@ extern crate user;

#[no_mangle]
fn main() -> i32 {
println!("Hello OS");
println!("Hello OS from app");
0
}
2 changes: 1 addition & 1 deletion user/src/linker.ld
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
OUTPUT_ARCH(riscv)
ENTRY(_start)
BASE_ADDRESS = 0x0;
BASE_ADDRESS = 0x80400000;

SECTIONS
{
Expand Down
1 change: 1 addition & 0 deletions user/src/scall_os.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ fn syscall(which: usize, args: [usize; 3]) -> isize {
in ("x12") args[2],
in("x17") which,
lateout("x10") ret,
options(nostack)
);
}
ret
Expand Down

0 comments on commit 1065854

Please sign in to comment.