mirror of
https://github.com/panpaul/tiny_os
synced 2024-09-20 09:45:19 +08:00
Compare commits
4 Commits
59fbc75552
...
9c95cb4f5e
Author | SHA1 | Date | |
---|---|---|---|
9c95cb4f5e | |||
9628d32d54 | |||
f86b061470 | |||
2252edf228 |
17
Cargo.lock
generated
17
Cargo.lock
generated
@ -14,6 +14,15 @@ version = "1.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
||||
|
||||
[[package]]
|
||||
name = "lazy_static"
|
||||
version = "1.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
|
||||
dependencies = [
|
||||
"spin",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "log"
|
||||
version = "0.4.20"
|
||||
@ -53,6 +62,12 @@ dependencies = [
|
||||
"static_assertions",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "spin"
|
||||
version = "0.5.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d"
|
||||
|
||||
[[package]]
|
||||
name = "static_assertions"
|
||||
version = "1.1.0"
|
||||
@ -63,8 +78,10 @@ checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
|
||||
name = "tiny_os"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"lazy_static",
|
||||
"log",
|
||||
"sbi-rt",
|
||||
"static_assertions",
|
||||
"uart_16550",
|
||||
]
|
||||
|
||||
|
10
Cargo.toml
10
Cargo.toml
@ -6,13 +6,15 @@ edition = "2021"
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[features]
|
||||
default = ["arch_riscv64", "board_virt"]
|
||||
default = ["arch_riscv64", "board_virt", "log_color"]
|
||||
arch_riscv64 = []
|
||||
arch_riscv32 = []
|
||||
arch_arm = []
|
||||
arch_x86 = []
|
||||
board_default = []
|
||||
board_virt = []
|
||||
board_thead = []
|
||||
log_color = []
|
||||
|
||||
[profile.dev]
|
||||
panic = "abort"
|
||||
@ -21,6 +23,8 @@ panic = "abort"
|
||||
panic = "abort"
|
||||
|
||||
[dependencies]
|
||||
sbi-rt = { version = "0.0.2", features = ["legacy"] }
|
||||
uart_16550 = "0.3"
|
||||
lazy_static = { version = "1.4.0", features = ["spin_no_std"] }
|
||||
log = "0.4"
|
||||
sbi-rt = { version = "0.0.2", features = ["legacy"] }
|
||||
static_assertions = "1.1.0"
|
||||
uart_16550 = "0.3"
|
||||
|
19
build.rs
19
build.rs
@ -1,19 +1,26 @@
|
||||
fn main() {
|
||||
println!("cargo:rerun-if-changed=build.rs");
|
||||
|
||||
struct TargetConfiguration {
|
||||
struct TargetConfig {
|
||||
target: &'static str,
|
||||
lds: &'static str,
|
||||
}
|
||||
|
||||
const TARGET_CONFIGURATIONS: &[TargetConfiguration] = &[TargetConfiguration {
|
||||
target: "riscv64",
|
||||
lds: "src/arch/riscv/boot/linker64.ld",
|
||||
}];
|
||||
const TARGET_LDS: &[TargetConfig] = &[
|
||||
TargetConfig {
|
||||
target: "riscv64",
|
||||
lds: "src/arch/riscv/linker.ld",
|
||||
},
|
||||
TargetConfig {
|
||||
target: "riscv32",
|
||||
lds: "src/arch/riscv/linker.ld",
|
||||
},
|
||||
];
|
||||
|
||||
let target = std::env::var("TARGET").unwrap();
|
||||
for cfg in TARGET_CONFIGURATIONS {
|
||||
for cfg in TARGET_LDS {
|
||||
if target.starts_with(cfg.target) {
|
||||
println!("cargo:rerun-if-changed={}", cfg.lds);
|
||||
println!("cargo:rustc-link-arg=-T{}", cfg.lds);
|
||||
return;
|
||||
}
|
||||
|
@ -1,8 +1,6 @@
|
||||
use core::fmt::Write;
|
||||
|
||||
pub struct RawConsole;
|
||||
|
||||
pub trait Printer: Write {
|
||||
pub trait Printer: core::fmt::Write {
|
||||
fn put_char(c: char);
|
||||
|
||||
#[inline]
|
||||
@ -64,7 +62,11 @@ pub trait Printer: Write {
|
||||
}
|
||||
}
|
||||
|
||||
impl Write for RawConsole {
|
||||
pub trait Reader {
|
||||
fn get_char() -> char;
|
||||
}
|
||||
|
||||
impl core::fmt::Write for RawConsole {
|
||||
fn write_str(&mut self, s: &str) -> core::fmt::Result {
|
||||
Self::put_str(s);
|
||||
Ok(())
|
||||
|
123
src/arch/riscv/asm/trap32.S
Normal file
123
src/arch/riscv/asm/trap32.S
Normal file
@ -0,0 +1,123 @@
|
||||
.section .trampoline_section
|
||||
|
||||
.global trampoline
|
||||
trampoline:
|
||||
|
||||
.align 4
|
||||
|
||||
.global __user2kernel
|
||||
__user2kernel:
|
||||
# load trapframe
|
||||
csrw sscratch, a0 # save a0, will be saved later
|
||||
li a0, {TRAPFRAME} # TRAPFRAME will be mapped to the same virtual address
|
||||
|
||||
# save GPRs
|
||||
sw ra, 0(a0)
|
||||
sw sp, 4(a0)
|
||||
sw gp, 8(a0)
|
||||
sw tp, 12(a0)
|
||||
sw t0, 16(a0)
|
||||
sw t1, 20(a0)
|
||||
sw t2, 24(a0)
|
||||
sw s0, 28(a0)
|
||||
sw s1, 32(a0)
|
||||
#sw a0, 36(a0)
|
||||
sw a1, 40(a0)
|
||||
sw a2, 44(a0)
|
||||
sw a3, 48(a0)
|
||||
sw a4, 52(a0)
|
||||
sw a5, 56(a0)
|
||||
sw a6, 60(a0)
|
||||
sw a7, 64(a0)
|
||||
sw s2, 68(a0)
|
||||
sw s3, 72(a0)
|
||||
sw s4, 76(a0)
|
||||
sw s5, 80(a0)
|
||||
sw s6, 84(a0)
|
||||
sw s7, 88(a0)
|
||||
sw s8, 92(a0)
|
||||
sw s9, 96(a0)
|
||||
sw s10, 100(a0)
|
||||
sw s11, 104(a0)
|
||||
sw t3, 108(a0)
|
||||
sw t4, 112(a0)
|
||||
sw t5, 116(a0)
|
||||
sw t6, 120(a0)
|
||||
|
||||
# save a0
|
||||
csrr t0, sscratch
|
||||
sw t0, 36(a0)
|
||||
|
||||
# save user epc / sstatus
|
||||
csrr t0, sepc
|
||||
csrr t1, sstatus
|
||||
sw t0, 124(a0)
|
||||
sw t1, 128(a0)
|
||||
|
||||
# restore kernel env
|
||||
lw sp, 132(a0) # kernel sp
|
||||
lw tp, 136(a0) # kernel tp
|
||||
lw t0, 140(a0) # trap handler
|
||||
lw t1, 144(a0) # page table
|
||||
|
||||
# load kernel page table
|
||||
sfence.vma zero, zero
|
||||
csrw satp, t1
|
||||
sfence.vma zero, zero
|
||||
|
||||
# jump to trap handler
|
||||
jr t0
|
||||
|
||||
.global __kernel2user
|
||||
__kernel2user:
|
||||
# restore user page table (a0)
|
||||
sfence.vma zero, zero
|
||||
csrw satp, a0
|
||||
sfence.vma zero, zero
|
||||
|
||||
li a0, {TRAPFRAME}
|
||||
|
||||
# restore user epc / sstatus
|
||||
lw t0, 124(a0)
|
||||
lw t1, 128(a0)
|
||||
csrw sepc, t0
|
||||
csrw sstatus, t1
|
||||
|
||||
# restore GPRs
|
||||
lw ra, 0(a0)
|
||||
lw sp, 4(a0)
|
||||
lw gp, 8(a0)
|
||||
lw tp, 12(a0)
|
||||
lw t0, 16(a0)
|
||||
lw t1, 20(a0)
|
||||
lw t2, 24(a0)
|
||||
lw s0, 28(a0)
|
||||
lw s1, 32(a0)
|
||||
#lw a0, 36(a0)
|
||||
lw a1, 40(a0)
|
||||
lw a2, 44(a0)
|
||||
lw a3, 48(a0)
|
||||
lw a4, 52(a0)
|
||||
lw a5, 56(a0)
|
||||
lw a6, 60(a0)
|
||||
lw a7, 64(a0)
|
||||
lw s2, 68(a0)
|
||||
lw s3, 72(a0)
|
||||
lw s4, 76(a0)
|
||||
lw s5, 80(a0)
|
||||
lw s6, 84(a0)
|
||||
lw s7, 88(a0)
|
||||
lw s8, 92(a0)
|
||||
lw s9, 96(a0)
|
||||
lw s10, 100(a0)
|
||||
lw s11, 104(a0)
|
||||
lw t3, 108(a0)
|
||||
lw t4, 112(a0)
|
||||
lw t5, 116(a0)
|
||||
lw t6, 120(a0)
|
||||
lw a0, 36(a0)
|
||||
|
||||
# go back to usermode
|
||||
sret
|
||||
|
||||
# vim:set ts=8 noexpandtab:
|
123
src/arch/riscv/asm/trap64.S
Normal file
123
src/arch/riscv/asm/trap64.S
Normal file
@ -0,0 +1,123 @@
|
||||
.section .trampoline_section
|
||||
|
||||
.global trampoline
|
||||
trampoline:
|
||||
|
||||
.align 4
|
||||
|
||||
.global __user2kernel
|
||||
__user2kernel:
|
||||
# load trapframe
|
||||
csrw sscratch, a0 # save a0, will be saved later
|
||||
li a0, {TRAPFRAME} # TRAPFRAME will be mapped to the same virtual address
|
||||
|
||||
# save GPRs
|
||||
sd ra, 0(a0)
|
||||
sd sp, 8(a0)
|
||||
sd gp, 16(a0)
|
||||
sd tp, 24(a0)
|
||||
sd t0, 32(a0)
|
||||
sd t1, 40(a0)
|
||||
sd t2, 48(a0)
|
||||
sd s0, 56(a0)
|
||||
sd s1, 64(a0)
|
||||
#sd a0, 72(a0)
|
||||
sd a1, 80(a0)
|
||||
sd a2, 88(a0)
|
||||
sd a3, 96(a0)
|
||||
sd a4, 104(a0)
|
||||
sd a5, 112(a0)
|
||||
sd a6, 120(a0)
|
||||
sd a7, 128(a0)
|
||||
sd s2, 136(a0)
|
||||
sd s3, 144(a0)
|
||||
sd s4, 152(a0)
|
||||
sd s5, 160(a0)
|
||||
sd s6, 168(a0)
|
||||
sd s7, 176(a0)
|
||||
sd s8, 184(a0)
|
||||
sd s9, 192(a0)
|
||||
sd s10, 200(a0)
|
||||
sd s11, 208(a0)
|
||||
sd t3, 216(a0)
|
||||
sd t4, 224(a0)
|
||||
sd t5, 232(a0)
|
||||
sd t6, 240(a0)
|
||||
|
||||
# save a0
|
||||
csrr t0, sscratch
|
||||
sd t0, 72(a0)
|
||||
|
||||
# save user epc / sstatus
|
||||
csrr t0, sepc
|
||||
csrr t1, sstatus
|
||||
sd t0, 248(a0)
|
||||
sd t1, 256(a0)
|
||||
|
||||
# restore kernel env
|
||||
ld sp, 264(a0) # kernel sp
|
||||
ld tp, 272(a0) # kernel tp
|
||||
ld t0, 280(a0) # trap handler
|
||||
ld t1, 288(a0) # page table
|
||||
|
||||
# load kernel page table
|
||||
sfence.vma zero, zero
|
||||
csrw satp, t1
|
||||
sfence.vma zero, zero
|
||||
|
||||
# jump to trap handler
|
||||
jr t0
|
||||
|
||||
.global __kernel2user
|
||||
__kernel2user:
|
||||
# restore user page table (a0)
|
||||
sfence.vma zero, zero
|
||||
csrw satp, a0
|
||||
sfence.vma zero, zero
|
||||
|
||||
li a0, {TRAPFRAME}
|
||||
|
||||
# restore user epc / sstatus
|
||||
ld t0, 248(a0)
|
||||
ld t1, 256(a0)
|
||||
csrw sepc, t0
|
||||
csrw sstatus, t1
|
||||
|
||||
# restore GPRs
|
||||
ld ra, 0(a0)
|
||||
ld sp, 8(a0)
|
||||
ld gp, 16(a0)
|
||||
ld tp, 24(a0)
|
||||
ld t0, 32(a0)
|
||||
ld t1, 40(a0)
|
||||
ld t2, 48(a0)
|
||||
ld s0, 56(a0)
|
||||
ld s1, 64(a0)
|
||||
#ld a0, 72(a0)
|
||||
ld a1, 80(a0)
|
||||
ld a2, 88(a0)
|
||||
ld a3, 96(a0)
|
||||
ld a4, 104(a0)
|
||||
ld a5, 112(a0)
|
||||
ld a6, 120(a0)
|
||||
ld a7, 128(a0)
|
||||
ld s2, 136(a0)
|
||||
ld s3, 144(a0)
|
||||
ld s4, 152(a0)
|
||||
ld s5, 160(a0)
|
||||
ld s6, 168(a0)
|
||||
ld s7, 176(a0)
|
||||
ld s8, 184(a0)
|
||||
ld s9, 192(a0)
|
||||
ld s10, 200(a0)
|
||||
ld s11, 208(a0)
|
||||
ld t3, 216(a0)
|
||||
ld t4, 224(a0)
|
||||
ld t5, 232(a0)
|
||||
ld t6, 240(a0)
|
||||
ld a0, 72(a0)
|
||||
|
||||
# go back to usermode
|
||||
sret
|
||||
|
||||
# vim:set ts=8 noexpandtab:
|
@ -1,3 +1,5 @@
|
||||
pub const UART0_BASE: usize = 0x1000_0000;
|
||||
pub const UART0_LSR: usize = 0x1000_0005;
|
||||
|
||||
pub mod printer;
|
||||
pub mod reader;
|
||||
|
@ -1,5 +1,11 @@
|
||||
use crate::arch::io::{Printer, RawConsole};
|
||||
|
||||
/*
|
||||
Theoretically, we should wait until
|
||||
"THR Empty" bit (1<<5 in LSR) is set
|
||||
before writing to UART.
|
||||
*/
|
||||
|
||||
impl Printer for RawConsole {
|
||||
#[inline]
|
||||
fn put_char(c: char) {
|
||||
|
11
src/arch/riscv/board/virt/reader.rs
Normal file
11
src/arch/riscv/board/virt/reader.rs
Normal file
@ -0,0 +1,11 @@
|
||||
use crate::arch::io::{RawConsole, Reader};
|
||||
|
||||
impl Reader for RawConsole {
|
||||
#[inline]
|
||||
fn get_char() -> char {
|
||||
let uart = super::UART0_BASE as *mut char;
|
||||
let line_sts = super::UART0_LSR as *mut u8;
|
||||
while unsafe { line_sts.read_volatile() } & 0x01 == 0 {}
|
||||
unsafe { uart.read_volatile() }
|
||||
}
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
#[allow(unused_imports)]
|
||||
use crate::arch::io::{Printer, RawConsole};
|
||||
use crate::arch::io::{Printer, RawConsole, Reader};
|
||||
|
||||
#[cfg(feature = "board_default")]
|
||||
impl Printer for RawConsole {
|
||||
@ -8,3 +8,17 @@ impl Printer for RawConsole {
|
||||
sbi_rt::legacy::console_putchar(c as usize);
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "board_default")]
|
||||
impl Reader for RawConsole {
|
||||
fn get_char() -> char {
|
||||
loop {
|
||||
#[allow(deprecated)]
|
||||
let ch = sbi_rt::legacy::console_getchar();
|
||||
if ch == usize::MAX {
|
||||
continue;
|
||||
}
|
||||
return ch as u8 as char;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
2
src/arch/riscv/layout.rs
Normal file
2
src/arch/riscv/layout.rs
Normal file
@ -0,0 +1,2 @@
|
||||
// TODO: currently a dummy value, figure out our memory layout
|
||||
pub const TRAPFRAME: usize = 0x8000_0000;
|
@ -14,6 +14,15 @@ SECTIONS {
|
||||
__text_start = .;
|
||||
*(.text.entry)
|
||||
*(.text .text.*)
|
||||
|
||||
. = ALIGN(0x1000);
|
||||
__trampoline_start = .;
|
||||
*(.trampoline_section)
|
||||
. = ALIGN(0x1000);
|
||||
__trampoline_end = .;
|
||||
|
||||
ASSERT(__trampoline_end - __trampoline_start == 0x1000, "trampoline larger than one page");
|
||||
|
||||
__text_end = .;
|
||||
} > DRAM
|
||||
|
@ -2,6 +2,9 @@
|
||||
#[path = "board/virt/mod.rs"]
|
||||
mod board;
|
||||
|
||||
mod layout;
|
||||
|
||||
pub mod entry;
|
||||
pub mod io;
|
||||
pub mod lowlevel;
|
||||
pub mod trap;
|
||||
|
37
src/arch/riscv/trap.rs
Normal file
37
src/arch/riscv/trap.rs
Normal file
@ -0,0 +1,37 @@
|
||||
use lazy_static::lazy_static;
|
||||
#[cfg(feature = "arch_riscv64")]
|
||||
core::arch::global_asm!(
|
||||
include_str!("./asm/trap64.S"),
|
||||
TRAPFRAME = const super::layout::TRAPFRAME
|
||||
);
|
||||
|
||||
#[cfg(feature = "arch_riscv32")]
|
||||
core::arch::global_asm!(
|
||||
include_str!("./asm/trap32.S"),
|
||||
TRAPFRAME = const super::layout::TRAPFRAME
|
||||
);
|
||||
|
||||
extern "C" {
|
||||
pub fn __user2kernel();
|
||||
pub fn __kernel2user(ctx: *mut TrapContext);
|
||||
}
|
||||
|
||||
// TODO: remove this when we have a real context switch
|
||||
lazy_static! {
|
||||
pub static ref __DUMMY: usize = unsafe {
|
||||
__user2kernel();
|
||||
__kernel2user(core::ptr::null_mut());
|
||||
42
|
||||
};
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub struct TrapContext {
|
||||
pub gprs: [usize; 31], // GPRs exclude zero
|
||||
pub user_sepc: usize, // 248/124 user program counter
|
||||
pub user_sstatus: usize, // 256/128 user status register
|
||||
pub kernel_sp: usize, // 264/132 kernel stack pointer
|
||||
pub kernel_tp: usize, // 272/136 kernel tp
|
||||
pub kernel_trap: usize, // 280/140 kernel trap handler
|
||||
pub kernel_satp: usize, // 288/144 kernel page table
|
||||
}
|
@ -3,6 +3,9 @@
|
||||
#![feature(naked_functions)]
|
||||
#![feature(panic_info_message)]
|
||||
#![feature(fmt_internals)]
|
||||
#![feature(stmt_expr_attributes)]
|
||||
|
||||
extern crate static_assertions;
|
||||
|
||||
// arch
|
||||
pub mod arch;
|
||||
|
@ -14,8 +14,27 @@ impl Log for SimpleLogger {
|
||||
return;
|
||||
}
|
||||
|
||||
let (color_prefix, color_reset) = if cfg!(feature = "log_color") {
|
||||
let color = match record.level() {
|
||||
log::Level::Error => "\x1b[31m",
|
||||
log::Level::Warn => "\x1b[33m",
|
||||
log::Level::Info => "\x1b[32m",
|
||||
log::Level::Debug => "\x1b[34m",
|
||||
log::Level::Trace => "\x1b[37m",
|
||||
};
|
||||
(color, "\x1b[0m")
|
||||
} else {
|
||||
("", "")
|
||||
};
|
||||
|
||||
RawConsole
|
||||
.write_fmt(format_args!("[{}] {}\n", record.level(), record.args()))
|
||||
.write_fmt(format_args!(
|
||||
"{}[{}] {}{}\n",
|
||||
color_prefix,
|
||||
record.level(),
|
||||
record.args(),
|
||||
color_reset
|
||||
))
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user