Location>code7788 >text

[rCore Study Notes 019] Testing the chapter implementation in main

Popularity:94 ℃/2024-07-30 16:28:14

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 thebatchto load programs and switch programs, andtrapUsed 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.

  1. Introduction of the above authoring module
    1. embeddinglink_app.S
    2. pull intobatch,trap,syscall
  2. Initialization Module
  3. 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 theMakefileFile 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 theAdduse 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 memberuse crate::trap::TrapContext;, and that's when we found out that actually in thesrc/trap/There's no statement in it.TrapContextThen 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 findTrapContextIt'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 thismoduleIf 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 memberriscv = { 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-analyzerThe 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.metadataexistenbaledis 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.textpart, and it is necessary to declare__alltrapscap (a poem)__restoreSo 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

  1. Exit because an exception was thrown
  2. funded directly byexit(main());abort

It's all going to fall intotrap, and then in thetrap_handlerThe process is handled as long as there are no unintended consequences.ExpectationBoth 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.