1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
//! `rust-kernel-riscv` is an open-source project that implements an operating system kernel on RISC-V architecture with Rust programming language. The project draws inspiration from several open-source implementations, such as [xv6-riscv](https://github.com/mit-pdos/xv6-riscv) and [zCore](https://github.com/rcore-os/zCore).
//!
//! - The kernel leverages Rust's asynchronous programming model to schedule threads in both the
//!   kernel and user space, which makes context switching more efficient and eliminates the need of
//!   allocating a separate kernel stack for each user process.
//!
//! - The kernel implements the kernel page-table isolation, which prevents the kernel space and the
//!   user space to share a same page table and mitigates potential Meltdown attacks.

#![no_std]
#![no_main]
#![feature(alloc_error_handler)]
#![feature(panic_info_message)]
#![feature(naked_functions)]

extern crate alloc;

#[macro_use]
mod console;
mod constant;
mod executor;
mod file;
mod lang_items;
mod logging;
mod mem;
mod sbi;
mod sync;
mod syscall;
mod task;
mod timer;

use core::arch::global_asm;

use log::info;

global_asm!(include_str!("asm/boot.asm"));
global_asm!(include_str!("asm/linkage.asm"));

/// Initializes the thread executor and spawns the `INIT_PROCESS`.
#[no_mangle]
pub fn rust_main() {
    clear_bss();
    logging::init();

    mem::init();

    timer::enable_timer_interrupt();
    timer::set_trigger();

    info!("rust-kernel has booted");
    file::print_bin_name();

    task::init();
    executor::init();
    executor::run_until_complete();

    sbi::shutdown();
}

/// Initializes the `.bss` section with zeros.
fn clear_bss() {
    extern "C" {
        /// The `bss_start` is a symbol declared in the `src/linker.ld`,
        /// which represent the start address of the `.bss` section.
        fn bss_start();
        /// The `bss_end` is a symbol declared in the `src/linker.ld`,
        /// which represent the end address of the `.bss` section.
        fn bss_end();
    }

    (bss_start as usize..bss_end as usize)
        .for_each(|address| unsafe { (address as *mut u8).write_volatile(0) })
}