write sth. upfront
This essay was written by a very rookie rookie. Please feel free to ask any questions.
You can contact: 1160712160@
GitHhub:/WindDevil (Nothing so far.
Batch processing of operating system startup and runtime processes
To put all the modules implemented in this chapter together to run a batch operating system, review this chapter and think about the process of running a batch operating system.
You can see that this chapter was completed roughly as shown in the figure:
As you can see at the kernel level, the most important thing is the implementation of thebatch
to load programs and switch programs, andtrap
Used to handle user-level requests.
Therefore, we just need to add theJust add the initialization of these two modules in the
compile
There are three main components.
- Introduction of the above authoring module
- embedding
link_app.S
- pull into
batch
,trap
,syscall
- embedding
- Initialization Module
- Start running the userland app
That's all that needs to be added:
pub mod batch;
pub mod syscall;
pub mod trap;
global_asm!(include_str!("link_app.S"));
pub fn rust_main() -> ! {
trap::init();
batch::init();
batch::run_next_app();
}
finalized:
//! The main module and entrypoint
//!
//! Various facilities of the kernels are implemented as submodules. The most
//! important ones are:
//!
//! - [`trap`]: Handles all cases of switching from userspace to the kernel
//! - [`syscall`]: System call handling and implementation
//!
//! The operating system also starts in this module. Kernel code starts
//! executing from ``, after which [`rust_main()`] is called to
//! initialize various pieces of functionality. (See its source code for
//! details.)
//!
//! We then call [`batch::run_next_app()`] and for the first time go to
//! userspace.
#![deny(missing_docs)]
#![deny(warnings)]
#![no_std]
#![no_main]
#![feature(panic_info_message)]
use core::arch::global_asm;
use log::*;
#[macro_use]
mod console;
pub mod batch;
mod lang_items;
mod logging;
mod sbi;
mod sync;
pub mod syscall;
pub mod trap;
global_asm!(include_str!(""));
global_asm!(include_str!("link_app.S"));
/// clear BSS segment
fn clear_bss() {
extern "C" {
fn sbss();
fn ebss();
}
unsafe {
core::slice::from_raw_parts_mut(sbss as usize as *mut u8, ebss as usize - sbss as usize)
.fill(0);
}
}
/// the rust entry-point of os
#[no_mangle]
pub fn rust_main() -> ! {
extern "C" {
fn stext(); // begin addr of text segment
fn etext(); // end addr of text segment
fn srodata(); // start addr of Read-Only data segment
fn erodata(); // end addr of Read-Only data ssegment
fn sdata(); // start addr of data segment
fn edata(); // end addr of data segment
fn sbss(); // start addr of BSS segment
fn ebss(); // end addr of BSS segment
fn boot_stack_lower_bound(); // stack lower bound
fn boot_stack_top(); // stack top
}
clear_bss();
logging::init();
println!("[kernel] Hello, world!");
trace!(
"[kernel] .text [{:#x}, {:#x})",
stext as usize,
etext as usize
);
debug!(
"[kernel] .rodata [{:#x}, {:#x})",
srodata as usize, erodata as usize
);
info!(
"[kernel] .data [{:#x}, {:#x})",
sdata as usize, edata as usize
);
warn!(
"[kernel] boot_stack top=bottom={:#x}, lower_bound={:#x}",
boot_stack_top as usize, boot_stack_lower_bound as usize
);
error!("[kernel] .bss [{:#x}, {:#x})", sbss as usize, ebss as usize);
trap::init();
batch::init();
batch::run_next_app();
}
compile and run
Use of the first chapter of theMakefile
File to compile and run with one click.
cd os
make run
First compile run.
error: expected expression, found keyword `extern`
--> src/:94:13
|
94 | extern "C"
| ^^^^^^ expected expression
error: cannot find macro `asm` in this scope
--> src/:84:9
|
84 | asm!("")
| ^^^
|
help: consider importing this macro
|
1 + use core::arch::asm;
|
error: cannot find macro `global_asm` in this scope
--> src/trap/:3:1
|
3 | global_asm!(include_str!(""));
| ^^^^^^^^^^
|
help: consider importing one of these items
|
3 + use core::arch::global_asm;
|
3 + use crate::global_asm;
|
error[E0412]: cannot find type `TrapContext` in this scope
--> src/:34:36
|
34 | pub fn push_context(&self, cx: TrapContext) -> &'static mut TrapContext {
| ^^^^^^^^^^^ not found in this scope
error[E0412]: cannot find type `TrapContext` in this scope
--> src/:34:65
|
34 | pub fn push_context(&self, cx: TrapContext) -> &'static mut TrapContext {
| ^^^^^^^^^^^ not found in this scope
error[E0412]: cannot find type `TrapContext` in this scope
--> src/:35:60
|
35 | let cx_ptr = (self.get_sp() - core::mem::size_of::<TrapContext>()) as *mut TrapContext;
| ^^^^^^^^^^^ not found in this scope
|
help: you might be missing a type parameter
|
30 | impl<TrapContext> KernelStack {
| +++++++++++++
error[E0412]: cannot find type `TrapContext` in this scope
--> src/:35:84
|
35 | let cx_ptr = (self.get_sp() - core::mem::size_of::<TrapContext>()) as *mut TrapContext;
| ^^^^^^^^^^^ not found in this scope
error[E0412]: cannot find type `RefCell` in this scope
--> src/sync/:5:12
|
5 | inner: RefCell<T>,
| ^^^^^^^ not found in this scope
|
help: consider importing this struct
|
3 + use core::cell::RefCell;
|
error[E0433]: failed to resolve: use of undeclared type `RefCell`
--> src/sync/:14:23
|
14 | Self { inner: RefCell::new(value) }
| ^^^^^^^ use of undeclared type `RefCell`
|
help: consider importing this struct
|
3 + use core::cell::RefCell;
|
error[E0412]: cannot find type `RefMut` in this scope
--> src/sync/:17:39
|
17 | pub fn exclusive_access(&self) -> RefMut<'_, T> {
| ^^^^^^ not found in this scope
|
help: consider importing this struct
|
3 + use core::cell::RefMut;
|
error[E0412]: cannot find type `TrapContext` in this scope
--> src/trap/:13:30
|
13 | pub fn trap_handler(cx: &mut TrapContext) -> &mut TrapContext {
| ^^^^^^^^^^^ not found in this scope
error[E0412]: cannot find type `TrapContext` in this scope
--> src/trap/:13:51
|
13 | pub fn trap_handler(cx: &mut TrapContext) -> &mut TrapContext {
| ^^^^^^^^^^^ not found in this scope
error[E0425]: cannot find function `syscall` in this scope
--> src/trap/:19:24
|
19 | [10] = syscall([17], [[10], [11], [12]]) as usize;
| ^^^^^^^ not found in this scope
|
help: consider importing this function
|
3 + use crate::syscall::syscall;
|
error[E0425]: cannot find function `run_next_app` in this scope
--> src/trap/:24:13
|
24 | run_next_app();
| ^^^^^^^^^^^^ not found in this scope
|
help: consider importing this function
|
3 + use crate::batch::run_next_app;
|
error[E0425]: cannot find function `run_next_app` in this scope
--> src/trap/:28:13
|
28 | run_next_app();
| ^^^^^^^^^^^^ not found in this scope
|
help: consider importing this function
|
3 + use crate::batch::run_next_app;
|
error[E0425]: cannot find function `init` in module `batch`
--> src/:88:12
|
88 | batch::init();
| ^^^^ not found in `batch`
|
help: consider importing one of these items
|
23 + use crate::logging::init;
|
23 + use crate::trap::init;
|
help: if you import `init`, refer to it directly
|
88 - batch::init();
88 + init();
|
error[E0308]: mismatched types
--> src/:80:41
|
80 | core::slice::from_raw_parts_mut(APP_BASE_ADDRESS as *const u8, APP_SIZE_LIMIT).fill(0);
| ------------------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ types differ in mutability
| |
| arguments to this function are incorrect
|
= note: expected raw pointer `*mut _`
found raw pointer `*const u8`
note: function defined here
--> /home/winddevil/.rustup/toolchains/nightly-2024-05-01-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/slice/:147:21
|
147 | pub const unsafe fn from_raw_parts_mut<'a, T>(data: *mut T, len: usize) -> &'a mut [T] {
| ^^^^^^^^^^^^^^^^^^
error[E0599]: the method `get` exists for struct `Lazy<UPSafeCell<AppManager>>`, but its trait bounds were not satisfied
--> src/:88:1
|
88 | / lazy_static!
89 | | {
90 | | static ref APP_MANAGER: UPSafeCell<AppManager> = unsafe
91 | | {
... |
110 | | };
111 | | }
| |_^ method cannot be called on `Lazy<UPSafeCell<AppManager>>` due to unsatisfied trait bounds
|
::: src/sync/:3:1
|
3 | pub struct UPSafeCell<T> {
| ------------------------ doesn't satisfy `UPSafeCell<AppManager>: Sized`
|
= note: the following trait bounds were not satisfied:
`{type error}: Sized`
which is required by `UPSafeCell<AppManager>: Sized`
= note: this error originates in the macro `__lazy_static_internal` which comes from the expansion of the macro `lazy_static` (in Nightly builds, run with -Z macro-backtrace for more info)
error[E0433]: failed to resolve: use of undeclared type `TrapContext`
--> src/:126:13
|
126 | TrapContext::app_init_context(APP_BASE_ADDRESS, USER_STACK.get_sp())
| ^^^^^^^^^^^ use of undeclared type `TrapContext`
error[E0425]: cannot find function `sys_write` in this scope
--> src/syscall/:5:26
|
5 | SYSCALL_WRITE => sys_write(args[0], args[1] as *const u8, args[2]),
| ^^^^^^^^^ not found in this scope
error[E0425]: cannot find function `sys_exit` in this scope
--> src/syscall/:6:25
|
6 | SYSCALL_EXIT => sys_exit(args[0] as i32),
| ^^^^^^^^ not found in this scope
error[E0433]: failed to resolve: use of undeclared crate or module `stvec`
--> src/trap/:8:9
|
8 | stvec::write(__alltraps as usize, TrapMode::Direct);
| ^^^^^ use of undeclared crate or module `stvec`
error[E0433]: failed to resolve: use of undeclared type `TrapMode`
--> src/trap/:8:43
|
8 | stvec::write(__alltraps as usize, TrapMode::Direct);
| ^^^^^^^^ use of undeclared type `TrapMode`
error[E0433]: failed to resolve: use of undeclared crate or module `scause`
--> src/trap/:14:18
|
14 | let scause = scause::read();
| ^^^^^^ use of undeclared crate or module `scause`
error[E0433]: failed to resolve: use of undeclared crate or module `stval`
--> src/trap/:15:17
|
15 | let stval = stval::read();
| ^^^^^ use of undeclared crate or module `stval`
error: unused variable: `metadata`
--> src/:9:23
|
9 | fn enabled(&self, metadata: &Metadata) -> bool
| ^^^^^^^^ help: if this is intentional, prefix it with an underscore: `_metadata`
|
note: the lint level is defined here
--> src/:18:9
|
18 | #![deny(warnings)]
| ^^^^^^^^
= note: `#[deny(unused_variables)]` implied by `#[deny(warnings)]`
error[E0433]: failed to resolve: use of undeclared type `Exception`
--> src/trap/:26:25
|
26 | Trap::Exception(Exception::IllegalInstruction) => {
| ^^^^^^^^^ use of undeclared type `Exception`
error[E0433]: failed to resolve: use of undeclared type `Trap`
--> src/trap/:26:9
|
26 | Trap::Exception(Exception::IllegalInstruction) => {
| ^^^^ use of undeclared type `Trap`
error[E0433]: failed to resolve: use of undeclared type `Exception`
--> src/trap/:22:25
|
22 | Trap::Exception(Exception::StorePageFault) => {
| ^^^^^^^^^ use of undeclared type `Exception`
error[E0433]: failed to resolve: use of undeclared type `Trap`
--> src/trap/:22:9
|
22 | Trap::Exception(Exception::StorePageFault) => {
| ^^^^ use of undeclared type `Trap`
error[E0433]: failed to resolve: use of undeclared type `Exception`
--> src/trap/:21:25
|
21 | Trap::Exception(Exception::StoreFault) |
| ^^^^^^^^^ use of undeclared type `Exception`
error[E0433]: failed to resolve: use of undeclared type `Trap`
--> src/trap/:17:9
|
17 | Trap::Exception(Exception::UserEnvCall) => {
| ^^^^ use of undeclared type `Trap`
error[E0433]: failed to resolve: use of undeclared type `Exception`
--> src/trap/:17:25
|
17 | Trap::Exception(Exception::UserEnvCall) => {
| ^^^^^^^^^ use of undeclared type `Exception`
error[E0433]: failed to resolve: use of undeclared type `Trap`
--> src/trap/:21:9
|
21 | Trap::Exception(Exception::StoreFault) |
| ^^^^ use of undeclared type `Trap`
Some errors have detailed explanations: E0308, E0412, E0425, E0433, E0599.
For more information about an error, try `rustc --explain E0308`.
error: could not compile `os` (bin "os") due to 34 previous errors
make: *** [Makefile:42: kernel] Error 101
See a large section of the error report do not rush, first look at the first easy to solve, can be solved.
First of all, in theAdd
use core::arch::asm;
:
error: cannot find macro `asm` in this scope
--> src/:84:9
|
84 | asm!("")
| ^^^
|
help: consider importing this macro
|
1 + use core::arch::asm;
|
Similarly, insrc/trap/
Add it in.use core::arch::global_asm;
:
error: cannot find macro `global_asm` in this scope
--> src/trap/:3:1
|
3 | global_asm!(include_str!(""));
| ^^^^^^^^^^
|
help: consider importing one of these items
|
3 + use core::arch::global_asm;
|
3 + use crate::global_asm;
|
existbecome a member
use crate::trap::TrapContext;
, and that's when we found out that actually in thesrc/trap/
There's no statement in it.TrapContext
Then declare inside themod context;
:
error[E0412]: cannot find type `TrapContext` in this scope
--> src/:34:36
|
34 | pub fn push_context(&self, cx: TrapContext) -> &'static mut TrapContext {
| ^^^^^^^^^^^ not found in this scope
There's a lot more to follow that you can't findTrapContext
It's a problem that could be solved.
existsrc/sync/
Adduse core::cell::{RefCell, RefMut};
:
error[E0412]: cannot find type `RefCell` in this scope
--> src/sync/:5:12
|
5 | inner: RefCell<T>,
| ^^^^^^^ not found in this scope
|
help: consider importing this struct
|
3 + use core::cell::RefCell;
|
error[E0412]: cannot find type `RefMut` in this scope
--> src/sync/:17:39
|
17 | pub fn exclusive_access(&self) -> RefMut<'_, T> {
| ^^^^^^ not found in this scope
|
help: consider importing this struct
|
3 + use core::cell::RefMut;
|
There is also a difficult dependency issue, if thismodule
If it is not self-implemented, then external dependencies are generally considered.
error[E0433]: failed to resolve: use of undeclared crate or module `riscv`
--> src/trap/:2:5
|
2 | use riscv::register::sstatus::{self, Sstatus, SPP};
| ^^^^^ use of undeclared crate or module `riscv`
existbecome a member
riscv = { git = "/rcore-os/riscv", features = ["inline-asm"] }
By the same token, to solve all such dependency problems.maybe is to correspond to this list of errors, but instead, you can choose to base it on therust-analyzer
The auto-reporting of errors, by the way.
Compile it again, and you'll find a lot of similar errors.
error: missing documentation for an associated function
This means that you are compiling a Rust project with a lint (compile-time checking rule) enabled, which requires all associated functions to be documented.
Then all we need to do is comment these functions.
And here's a new one.
error: unused variable: `metadata`
--> src/:9:23
|
9 | fn enabled(&self, metadata: &Metadata) -> bool
| ^^^^^^^^ help: if this is intentional, prefix it with an underscore: `_metadata`
|
Because of this.metadata
existenbaled
is not called in the function, so it needs to be preceded by an underscore._
, thus stating that this parameter is intentionally not called.
Also.Needs to be linked to
.text
part, and it is necessary to declare__alltraps
cap (a poem)__restore
So this needs to be added.
.section .text
.globl __alltraps
.globl __restore
finalFor.
.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
.globl __alltraps
.globl __restore
.align 2
__alltraps:
csrrw sp, sscratch, sp
# now sp->kernel stack, sscratch->user stack
# allocate a TrapContext on kernel stack
addi sp, sp, -34*8
# save 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 were saved on kernel stack
csrr t0, sstatus
csrr t1, sepc
sd t0, 32*8(sp)
sd t1, 33*8(sp)
# read user stack from sscratch and save it on the kernel stack
csrr t2, sscratch
sd t2, 2*8(sp)
# set input argument of trap_handler(cx: &mut TrapContext)
mv a0, sp
call trap_handler
__restore:
# case1: start running app by __restore
# case2: back to U after handling trap
mv sp, a0
# now sp->kernel stack(after allocated), sscratch->user stack
# restore sstatus/sepc
ld t0, 32*8(sp)
ld t1, 33*8(sp)
ld t2, 2*8(sp)
csrw sstatus, t0
csrw sepc, t1
csrw sscratch, t2
# restore general-purpuse registers except 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
# release TrapContext on kernel stack
addi sp, sp, 34*8
# now sp->kernel stack, sscratch->user stack
csrrw sp, sscratch, sp
sret
The final run results in.
[rustsbi] RustSBI version 0.3.1, adapting to RISC-V SBI v1.0.0
.______ __ __ _______.___________. _______..______ __
| _ \ | | | | / | | / || _ \ | |
| |_) | | | | | | (----`---| |----`| (----`| |_) || |
| / | | | | \ \ | | \ \ | _ < | |
| |\ \----.| `--' |.----) | | | .----) | | |_) || |
| _| `._____| \______/ |_______/ |__| |_______/ |______/ |__|
[rustsbi] Implementation : RustSBI-QEMU Version 0.2.0-alpha.2
[rustsbi] Platform Name : riscv-virtio,qemu
[rustsbi] Platform SMP : 1
[rustsbi] Platform Memory : 0x80000000..0x88000000
[rustsbi] Boot HART : 0
[rustsbi] Device Tree Region : 0x87000000..0x87000f02
[rustsbi] Firmware Address : 0x80000000
[rustsbi] Supervisor Address : 0x80200000
[rustsbi] pmp01: 0x00000000..0x80000000 (-wr)
[rustsbi] pmp02: 0x80000000..0x80200000 (---)
[rustsbi] pmp03: 0x80200000..0x88000000 (xwr)
[rustsbi] pmp04: 0x88000000..0x00000000 (-wr)
[kernel] Hello, world!
[kernel] num_app = 5
[kernel] app_0 [0x8020a038, 0x8020b360)
[kernel] app_1 [0x8020b360, 0x8020c730)
[kernel] app_2 [0x8020c730, 0x8020dcd8)
[kernel] app_3 [0x8020dcd8, 0x8020f090)
[kernel] app_4 [0x8020f090, 0x80210440)
[kernel] Loading app_0
Hello, world!
[kernel] Application exited with code 0
[kernel] Loading app_1
Into Test store_fault, we will insert an invalid store operation...
Kernel should kill this application!
[kernel] PageFault in application, kernel killed it.
[kernel] Loading app_2
3^10000=5079(MOD 10007)
3^20000=8202(MOD 10007)
3^30000=8824(MOD 10007)
3^40000=5750(MOD 10007)
3^50000=3824(MOD 10007)
3^60000=8516(MOD 10007)
3^70000=2510(MOD 10007)
3^80000=9379(MOD 10007)
3^90000=2621(MOD 10007)
3^100000=2749(MOD 10007)
Test power OK!
[kernel] Application exited with code 0
[kernel] Loading app_3
Try to execute privileged instruction in U Mode
Kernel should kill this application!
[kernel] IllegalInstruction in application, kernel killed it.
[kernel] Loading app_4
Try to access privileged CSR in U Mode
Kernel should kill this application!
[kernel] IllegalInstruction in application, kernel killed it.
All applications completed!
You can see that after starting the batch system, each app runs and then remembers the user level.The startup section for each app is written in.
#[no_mangle]
#[link_section = "."]
pub extern "C" fn _start() -> ! {
clear_bss();
exit(main());
panic!("unreachable after sys_exit!");
}
After each run, the
- Exit because an exception was thrown
- funded directly by
exit(main());
abort
It's all going to fall intotrap
, and then in thetrap_handler
The process is handled as long as there are no unintended consequences.Expectation
Both will call therun_next_app
, so all the apps run sequentially.
This chapter ended perfectly, I'm such a lazy dog, I have to step in every hole all the time.