From a78916c57e42654cadb0de54d79bff278027b699 Mon Sep 17 00:00:00 2001 From: Yuhao Zhou Date: Sun, 31 Mar 2019 22:04:22 +0800 Subject: [PATCH 01/85] Add MIPS target. --- kernel/Cargo.lock | 7 + kernel/Cargo.toml | 3 + kernel/Makefile | 9 +- kernel/src/arch/mipsel/atomic.patch | 72 +++++ kernel/src/arch/mipsel/board/u540/linker.ld | 49 ++++ kernel/src/arch/mipsel/board/u540/mod.rs | 18 ++ kernel/src/arch/mipsel/boot/entry.asm | 19 ++ kernel/src/arch/mipsel/boot/linker.ld | 54 ++++ kernel/src/arch/mipsel/boot/linker64.ld | 49 ++++ kernel/src/arch/mipsel/boot/trap.asm | 129 +++++++++ kernel/src/arch/mipsel/compiler_rt.rs | 8 + kernel/src/arch/mipsel/consts.rs | 42 +++ kernel/src/arch/mipsel/context.rs | 273 +++++++++++++++++++ kernel/src/arch/mipsel/cpu.rs | 38 +++ kernel/src/arch/mipsel/interrupt.rs | 127 +++++++++ kernel/src/arch/mipsel/io.rs | 52 ++++ kernel/src/arch/mipsel/memory.rs | 93 +++++++ kernel/src/arch/mipsel/mod.rs | 88 ++++++ kernel/src/arch/mipsel/paging.rs | 253 +++++++++++++++++ kernel/src/arch/mipsel/rand.rs | 3 + kernel/src/arch/mipsel/sbi.rs | 64 +++++ kernel/src/arch/mipsel/syscall.rs | 285 ++++++++++++++++++++ kernel/src/arch/mipsel/timer.rs | 40 +++ kernel/targets/mipsel.json | 36 +++ 24 files changed, 1810 insertions(+), 1 deletion(-) create mode 100644 kernel/src/arch/mipsel/atomic.patch create mode 100644 kernel/src/arch/mipsel/board/u540/linker.ld create mode 100644 kernel/src/arch/mipsel/board/u540/mod.rs create mode 100644 kernel/src/arch/mipsel/boot/entry.asm create mode 100644 kernel/src/arch/mipsel/boot/linker.ld create mode 100644 kernel/src/arch/mipsel/boot/linker64.ld create mode 100644 kernel/src/arch/mipsel/boot/trap.asm create mode 100644 kernel/src/arch/mipsel/compiler_rt.rs create mode 100644 kernel/src/arch/mipsel/consts.rs create mode 100644 kernel/src/arch/mipsel/context.rs create mode 100644 kernel/src/arch/mipsel/cpu.rs create mode 100644 kernel/src/arch/mipsel/interrupt.rs create mode 100644 kernel/src/arch/mipsel/io.rs create mode 100644 kernel/src/arch/mipsel/memory.rs create mode 100644 kernel/src/arch/mipsel/mod.rs create mode 100644 kernel/src/arch/mipsel/paging.rs create mode 100644 kernel/src/arch/mipsel/rand.rs create mode 100644 kernel/src/arch/mipsel/sbi.rs create mode 100644 kernel/src/arch/mipsel/syscall.rs create mode 100644 kernel/src/arch/mipsel/timer.rs create mode 100644 kernel/targets/mipsel.json diff --git a/kernel/Cargo.lock b/kernel/Cargo.lock index 33aa5a6..4278bba 100644 --- a/kernel/Cargo.lock +++ b/kernel/Cargo.lock @@ -227,6 +227,11 @@ name = "managed" version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "mips" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "nodrop" version = "0.1.13" @@ -309,6 +314,7 @@ dependencies = [ "isomorphic_drivers 0.1.0 (git+https://github.com/rcore-os/isomorphic_drivers)", "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "mips 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "once 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "pc-keyboard 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", "raw-cpuid 6.1.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -607,6 +613,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "e19e8d5c34a3e0e2223db8e060f9e8264aeeb5c5fc64a4ee9965c062211c024b" "checksum log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c84ec4b527950aa83a329754b01dbe3f58361d1c5efacd1f6d68c494d08a17c6" "checksum managed 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "fdcec5e97041c7f0f1c5b7d93f12e57293c831c646f4cc7a5db59460c7ea8de6" +"checksum mips 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f79c54c0ff7e933ffe5b3ec7c3c05037b654c334b0c98e66536d2d8906435394" "checksum nodrop 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "2f9667ddcc6cc8a43afc9b7917599d7216aa09c463919ea32c59ed6cac8bc945" "checksum once 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "931fb7a4cf34610cf6cbe58d52a8ca5ef4c726d4e2e178abd0dc13a6551c6d73" "checksum os_bootinfo 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "66481dbeb5e773e7bd85b63cd6042c30786f834338288c5ec4f3742673db360a" diff --git a/kernel/Cargo.toml b/kernel/Cargo.toml index aa60642..1292af8 100644 --- a/kernel/Cargo.toml +++ b/kernel/Cargo.toml @@ -69,6 +69,9 @@ riscv = { git = "https://github.com/rcore-os/riscv", features = ["inline-asm"] } aarch64 = { git = "https://github.com/rcore-os/aarch64" } bcm2837 = { git = "https://github.com/rcore-os/bcm2837", optional = true } +[target.'cfg(target_arch = "mipsel")'.dependencies] +mips = "^0.1.0" + [package.metadata.bootimage] default-target = "targets/x86_64.json" output = "target/x86_64/bootimage.bin" diff --git a/kernel/Makefile b/kernel/Makefile index 6a82f38..3a077d7 100644 --- a/kernel/Makefile +++ b/kernel/Makefile @@ -15,7 +15,7 @@ # make clean Clean # # Options: -# arch = x86_64 | riscv32 | riscv64 | aarch64 +# arch = x86_64 | riscv32 | riscv64 | aarch64 | mipsel # d = int | in_asm | ... QEMU debug info # mode = debug | release # LOG = off | error | warn | info | debug | trace @@ -155,6 +155,8 @@ else ifeq ($(arch), riscv32) prefix := riscv64-unknown-elf- else ifeq ($(arch), riscv64) prefix := riscv64-unknown-elf- +else ifeq ($(arch), mipsel) +prefix ?= mipsel-linux-gnu- else ifeq ($(arch), aarch64) prefix ?= aarch64-none-elf- ifeq (,$(shell which $(prefix)ld)) @@ -251,6 +253,9 @@ else ifeq ($(arch), riscv64) cp bbl $(abspath $@) else ifeq ($(arch), aarch64) @$(objcopy) $(bootloader) --strip-all -O binary $@ +else ifeq ($(arch), mipsel) + # TODO write mipsel bootloader + false endif kernel: @@ -271,6 +276,8 @@ else ifeq ($(arch), riscv64) @cargo xbuild $(build_args) else ifeq ($(arch), aarch64) @cargo xbuild $(build_args) +else ifeq ($(arch), mipsel) + @cargo xbuild $(build_args) endif diff --git a/kernel/src/arch/mipsel/atomic.patch b/kernel/src/arch/mipsel/atomic.patch new file mode 100644 index 0000000..d7722b6 --- /dev/null +++ b/kernel/src/arch/mipsel/atomic.patch @@ -0,0 +1,72 @@ +--- atomic_backup.rs 2018-10-06 19:59:14.000000000 +0800 ++++ atomic.rs 2018-10-26 14:34:31.000000000 +0800 +@@ -125,6 +125,9 @@ + #[cfg(target_has_atomic = "8")] + #[stable(feature = "rust1", since = "1.0.0")] + pub struct AtomicBool { ++ #[cfg(any(target_arch = "riscv32", target_arch = "riscv64"))] ++ v: UnsafeCell, ++ #[cfg(not(any(target_arch = "riscv32", target_arch = "riscv64")))] + v: UnsafeCell, + } + +@@ -265,6 +268,59 @@ + pub const ATOMIC_BOOL_INIT: AtomicBool = AtomicBool::new(false); + + #[cfg(target_has_atomic = "8")] ++#[cfg(any(target_arch = "riscv32", target_arch = "riscv64"))] ++impl AtomicBool { ++ /// ++ #[inline] ++ #[stable(feature = "rust1", since = "1.0.0")] ++ pub const fn new(v: bool) -> AtomicBool { ++ AtomicBool { v: UnsafeCell::new(v as u32) } ++ } ++ ++ /// ++ #[inline] ++ #[stable(feature = "rust1", since = "1.0.0")] ++ pub fn load(&self, order: Ordering) -> bool { ++ unsafe { atomic_load(self.v.get(), order) != 0 } ++ } ++ ++ /// ++ #[inline] ++ #[stable(feature = "rust1", since = "1.0.0")] ++ pub fn store(&self, val: bool, order: Ordering) { ++ unsafe { atomic_store(self.v.get(), val as u32, order); } ++ } ++ ++ /// ++ #[inline] ++ #[stable(feature = "rust1", since = "1.0.0")] ++ pub fn compare_and_swap(&self, current: bool, new: bool, order: Ordering) -> bool { ++ match self.compare_exchange(current, new, order, strongest_failure_ordering(order)) { ++ Ok(x) => x, ++ Err(x) => x, ++ } ++ } ++ ++ /// ++ #[inline] ++ #[stable(feature = "extended_compare_and_swap", since = "1.10.0")] ++ pub fn compare_exchange(&self, ++ current: bool, ++ new: bool, ++ success: Ordering, ++ failure: Ordering) ++ -> Result { ++ match unsafe { ++ atomic_compare_exchange(self.v.get(), current as u32, new as u32, success, failure) ++ } { ++ Ok(x) => Ok(x != 0), ++ Err(x) => Err(x != 0), ++ } ++ } ++} ++ ++#[cfg(target_has_atomic = "8")] ++#[cfg(not(any(target_arch = "riscv32", target_arch = "riscv64")))] + impl AtomicBool { + /// Creates a new `AtomicBool`. + /// diff --git a/kernel/src/arch/mipsel/board/u540/linker.ld b/kernel/src/arch/mipsel/board/u540/linker.ld new file mode 100644 index 0000000..6bbe85b --- /dev/null +++ b/kernel/src/arch/mipsel/board/u540/linker.ld @@ -0,0 +1,49 @@ +/* Copy from bbl-ucore : https://ring00.github.io/bbl-ucore */ + +/* Simple linker script for the ucore kernel. + See the GNU ld 'info' manual ("info ld") to learn the syntax. */ + +OUTPUT_ARCH(riscv) +ENTRY(_start) + +BASE_ADDRESS = 0xffffffffc0020000; + +SECTIONS +{ + /* Load the kernel at this address: "." means the current address */ + . = BASE_ADDRESS; + start = .; + + .text : { + stext = .; + *(.text.entry) + *(.text .text.*) + . = ALIGN(4K); + etext = .; + } + + .rodata : { + srodata = .; + *(.rodata .rodata.*) + . = ALIGN(4K); + erodata = .; + } + + .data : { + sdata = .; + *(.data .data.*) + edata = .; + } + + .stack : { + *(.bss.stack) + } + + .bss : { + sbss = .; + *(.bss .bss.*) + ebss = .; + } + + PROVIDE(end = .); +} diff --git a/kernel/src/arch/mipsel/board/u540/mod.rs b/kernel/src/arch/mipsel/board/u540/mod.rs new file mode 100644 index 0000000..cc53874 --- /dev/null +++ b/kernel/src/arch/mipsel/board/u540/mod.rs @@ -0,0 +1,18 @@ +use super::consts::KERNEL_OFFSET; + +/// Mask all external interrupt except serial. +pub unsafe fn init_external_interrupt() { + const HART1_S_MODE_INTERRUPT_ENABLES: *mut u64 = (KERNEL_OFFSET + 0x0C00_2100) as *mut u64; + const SERIAL: u64 = 4; + HART1_S_MODE_INTERRUPT_ENABLES.write(1 << SERIAL); +} + +/// Claim and complete external interrupt by reading and writing to +/// PLIC Interrupt Claim/Complete Register. +pub unsafe fn handle_external_interrupt() { + const HART1_S_MODE_INTERRUPT_CLAIM_COMPLETE: *mut u32 = (KERNEL_OFFSET + 0x0C20_2004) as *mut u32; + // claim + let source = HART1_S_MODE_INTERRUPT_CLAIM_COMPLETE.read(); + // complete + HART1_S_MODE_INTERRUPT_CLAIM_COMPLETE.write(source); +} \ No newline at end of file diff --git a/kernel/src/arch/mipsel/boot/entry.asm b/kernel/src/arch/mipsel/boot/entry.asm new file mode 100644 index 0000000..3cee2fd --- /dev/null +++ b/kernel/src/arch/mipsel/boot/entry.asm @@ -0,0 +1,19 @@ + .section .text.entry + .globl _start +_start: + add t0, a0, 1 + slli t0, t0, 16 + + lui sp, %hi(bootstack) + addi sp, sp, %lo(bootstack) + add sp, sp, t0 + + call rust_main + + .section .bss.stack + .align 12 #PGSHIFT + .global bootstack +bootstack: + .space 4096 * 16 * 8 + .global bootstacktop +bootstacktop: diff --git a/kernel/src/arch/mipsel/boot/linker.ld b/kernel/src/arch/mipsel/boot/linker.ld new file mode 100644 index 0000000..bc3ba7f --- /dev/null +++ b/kernel/src/arch/mipsel/boot/linker.ld @@ -0,0 +1,54 @@ +/* Copy from bbl-ucore : https://ring00.github.io/bbl-ucore */ + +/* Simple linker script for the ucore kernel. + See the GNU ld 'info' manual ("info ld") to learn the syntax. */ + +OUTPUT_ARCH(riscv) +ENTRY(_start) + +BASE_ADDRESS = 0xC0020000; + +SECTIONS +{ + . = 0xC0000000; + .boot : { + KEEP(*(.text.boot)) + } + + /* Load the kernel at this address: "." means the current address */ + . = BASE_ADDRESS; + start = .; + + .text : { + stext = .; + *(.text.entry) + *(.text .text.*) + . = ALIGN(4K); + etext = .; + } + + .rodata : { + srodata = .; + *(.rodata .rodata.*) + . = ALIGN(4K); + erodata = .; + } + + .data : { + sdata = .; + *(.data .data.*) + edata = .; + } + + .stack : { + *(.bss.stack) + } + + .bss : { + sbss = .; + *(.bss .bss.*) + ebss = .; + } + + PROVIDE(end = .); +} diff --git a/kernel/src/arch/mipsel/boot/linker64.ld b/kernel/src/arch/mipsel/boot/linker64.ld new file mode 100644 index 0000000..6bbe85b --- /dev/null +++ b/kernel/src/arch/mipsel/boot/linker64.ld @@ -0,0 +1,49 @@ +/* Copy from bbl-ucore : https://ring00.github.io/bbl-ucore */ + +/* Simple linker script for the ucore kernel. + See the GNU ld 'info' manual ("info ld") to learn the syntax. */ + +OUTPUT_ARCH(riscv) +ENTRY(_start) + +BASE_ADDRESS = 0xffffffffc0020000; + +SECTIONS +{ + /* Load the kernel at this address: "." means the current address */ + . = BASE_ADDRESS; + start = .; + + .text : { + stext = .; + *(.text.entry) + *(.text .text.*) + . = ALIGN(4K); + etext = .; + } + + .rodata : { + srodata = .; + *(.rodata .rodata.*) + . = ALIGN(4K); + erodata = .; + } + + .data : { + sdata = .; + *(.data .data.*) + edata = .; + } + + .stack : { + *(.bss.stack) + } + + .bss : { + sbss = .; + *(.bss .bss.*) + ebss = .; + } + + PROVIDE(end = .); +} diff --git a/kernel/src/arch/mipsel/boot/trap.asm b/kernel/src/arch/mipsel/boot/trap.asm new file mode 100644 index 0000000..17ff77e --- /dev/null +++ b/kernel/src/arch/mipsel/boot/trap.asm @@ -0,0 +1,129 @@ +# Constants / Macros defined in Rust code: +# XLENB +# LOAD +# STORE +# TEST_BACK_TO_KERNEL + +.macro SAVE_ALL + # If coming from userspace, preserve the user stack pointer and load + # the kernel stack pointer. If we came from the kernel, sscratch + # will contain 0, and we should continue on the current stack. + csrrw sp, sscratch, sp + bnez sp, trap_from_user +trap_from_kernel: + csrr sp, sscratch + STORE gp, -1 + # sscratch = previous-sp, sp = kernel-sp +trap_from_user: + # provide room for trap frame + addi sp, sp, -37 * XLENB + # save x registers except x2 (sp) + STORE x1, 1 + STORE x3, 3 + STORE x4, 4 + STORE x5, 5 + STORE x6, 6 + STORE x7, 7 + STORE x8, 8 + STORE x9, 9 + STORE x10, 10 + STORE x11, 11 + STORE x12, 12 + STORE x13, 13 + STORE x14, 14 + STORE x15, 15 + STORE x16, 16 + STORE x17, 17 + STORE x18, 18 + STORE x19, 19 + STORE x20, 20 + STORE x21, 21 + STORE x22, 22 + STORE x23, 23 + STORE x24, 24 + STORE x25, 25 + STORE x26, 26 + STORE x27, 27 + STORE x28, 28 + STORE x29, 29 + STORE x30, 30 + STORE x31, 31 + + # load hartid to gp from sp[36] + LOAD gp, 36 + + # get sp, sstatus, sepc, stval, scause + # set sscratch = 0 + csrrw s0, sscratch, x0 + csrr s1, sstatus + csrr s2, sepc + csrr s3, stval + csrr s4, scause + # store sp, sstatus, sepc, sbadvaddr, scause + STORE s0, 2 + STORE s1, 32 + STORE s2, 33 + STORE s3, 34 + STORE s4, 35 +.endm + +.macro RESTORE_ALL + LOAD s1, 32 # s1 = sstatus + LOAD s2, 33 # s2 = sepc + andi s0, s1, 1 << 8 # sstatus.SPP = 1 + bnez s0, _to_kernel # s0 = back to kernel? +_to_user: + addi s0, sp, 37*XLENB + csrw sscratch, s0 # sscratch = kernel-sp + STORE gp, 36 # store hartid from gp to sp[36] +_to_kernel: + # restore sstatus, sepc + csrw sstatus, s1 + csrw sepc, s2 + + # restore x registers except x2 (sp) + LOAD x1, 1 + LOAD x3, 3 + LOAD x4, 4 + LOAD x5, 5 + LOAD x6, 6 + LOAD x7, 7 + LOAD x8, 8 + LOAD x9, 9 + LOAD x10, 10 + LOAD x11, 11 + LOAD x12, 12 + LOAD x13, 13 + LOAD x14, 14 + LOAD x15, 15 + LOAD x16, 16 + LOAD x17, 17 + LOAD x18, 18 + LOAD x19, 19 + LOAD x20, 20 + LOAD x21, 21 + LOAD x22, 22 + LOAD x23, 23 + LOAD x24, 24 + LOAD x25, 25 + LOAD x26, 26 + LOAD x27, 27 + LOAD x28, 28 + LOAD x29, 29 + LOAD x30, 30 + LOAD x31, 31 + # restore sp last + LOAD x2, 2 +.endm + + .section .text + .globl trap_entry +trap_entry: + SAVE_ALL + mv a0, sp + jal rust_trap + .globl trap_return +trap_return: + RESTORE_ALL + # return from supervisor call + sret diff --git a/kernel/src/arch/mipsel/compiler_rt.rs b/kernel/src/arch/mipsel/compiler_rt.rs new file mode 100644 index 0000000..b49a3ce --- /dev/null +++ b/kernel/src/arch/mipsel/compiler_rt.rs @@ -0,0 +1,8 @@ +//! Workaround for missing compiler-builtin symbols +//! +//! [atomic](http://llvm.org/docs/Atomics.html#libcalls-atomic) + +#[no_mangle] +pub extern fn abort() { + panic!("abort"); +} diff --git a/kernel/src/arch/mipsel/consts.rs b/kernel/src/arch/mipsel/consts.rs new file mode 100644 index 0000000..3aecac1 --- /dev/null +++ b/kernel/src/arch/mipsel/consts.rs @@ -0,0 +1,42 @@ +// Physical address available on THINPAD: +// [0x80000000, 0x80800000] +#[cfg(target_arch = "riscv32")] +pub const RECURSIVE_INDEX: usize = 0x3fd; +#[cfg(target_arch = "riscv64")] +pub const RECURSIVE_INDEX: usize = 0o774; +// Under riscv64, upon booting, paging is enabled by bbl and +// root_table[0777] maps to p3_table, +// and p3_table[0777] maps to gigapage 8000_0000H, +// so 0xFFFF_FFFF_8000_0000 maps to 0x8000_0000 +// root_table[0774] points to root_table itself as page table +// root_table[0775] points to root_table itself as leaf page +// root_table[0776] points to a temp page table as leaf page + +#[cfg(target_arch = "riscv32")] +pub const KERNEL_OFFSET: usize = 0xC000_0000; +#[cfg(target_arch = "riscv64")] +pub const KERNEL_OFFSET: usize = 0xFFFF_FFFF_C000_0000; + +#[cfg(target_arch = "riscv32")] +pub const KERNEL_P2_INDEX: usize = (KERNEL_OFFSET >> 12 >> 10) & 0x3ff; +#[cfg(target_arch = "riscv64")] +pub const KERNEL_P4_INDEX: usize = (KERNEL_OFFSET >> 12 >> 9 >> 9 >> 9) & 0o777; + +pub const KERNEL_HEAP_SIZE: usize = 0x00a0_0000; + +#[cfg(target_arch = "riscv32")] +pub const MEMORY_OFFSET: usize = 0x8000_0000; +#[cfg(target_arch = "riscv64")] +pub const MEMORY_OFFSET: usize = 0x8000_0000; + +#[cfg(target_arch = "riscv32")] +pub const MEMORY_END: usize = 0x8100_0000; +#[cfg(target_arch = "riscv64")] +pub const MEMORY_END: usize = 0x8100_0000; + +// FIXME: rv64 `sh` and `ls` will crash if stack top > 0x80000000 ??? +pub const USER_STACK_OFFSET: usize = 0x80000000 - USER_STACK_SIZE; +pub const USER_STACK_SIZE: usize = 0x10000; +pub const USER32_STACK_OFFSET: usize = 0xC0000000 - USER_STACK_SIZE; + +pub const MAX_DTB_SIZE: usize = 0x2000; \ No newline at end of file diff --git a/kernel/src/arch/mipsel/context.rs b/kernel/src/arch/mipsel/context.rs new file mode 100644 index 0000000..a8b6e5f --- /dev/null +++ b/kernel/src/arch/mipsel/context.rs @@ -0,0 +1,273 @@ +use riscv::register::{ + sstatus, + sstatus::Sstatus, + scause::Scause, +}; + +/// Saved registers on a trap. +#[derive(Clone)] +#[repr(C)] +pub struct TrapFrame { + /// General registers + pub x: [usize; 32], + /// Supervisor Status + pub sstatus: Sstatus, + /// Supervisor Exception Program Counter + pub sepc: usize, + /// Supervisor Trap Value + pub stval: usize, + /// Supervisor Cause + pub scause: Scause, + /// Reserve space for hartid + pub _hartid: usize, +} + +impl TrapFrame { + /// Constructs TrapFrame for a new kernel thread. + /// + /// The new thread starts at function `entry` with an usize argument `arg`. + /// The stack pointer will be set to `sp`. + fn new_kernel_thread(entry: extern fn(usize) -> !, arg: usize, sp: usize) -> Self { + use core::mem::zeroed; + let mut tf: Self = unsafe { zeroed() }; + tf.x[10] = arg; // a0 + tf.x[2] = sp; + tf.sepc = entry as usize; + tf.sstatus = sstatus::read(); + tf.sstatus.set_spie(true); + tf.sstatus.set_sie(false); + tf.sstatus.set_spp(sstatus::SPP::Supervisor); + tf + } + + /// Constructs TrapFrame for a new user thread. + /// + /// The new thread starts at `entry_addr`. + /// The stack pointer will be set to `sp`. + fn new_user_thread(entry_addr: usize, sp: usize) -> Self { + use core::mem::zeroed; + let mut tf: Self = unsafe { zeroed() }; + tf.x[2] = sp; + tf.sepc = entry_addr; + tf.sstatus = sstatus::read(); + tf.sstatus.set_spie(true); + tf.sstatus.set_sie(false); + tf.sstatus.set_spp(sstatus::SPP::User); + tf + } +} + +use core::fmt::{Debug, Formatter, Error}; +impl Debug for TrapFrame { + fn fmt(&self, f: &mut Formatter) -> Result<(), Error> { + struct Regs<'a>(&'a [usize; 32]); + impl<'a> Debug for Regs<'a> { + fn fmt(&self, f: &mut Formatter) -> Result<(), Error> { + const REG_NAME: [&str; 32] = [ + "zero", "ra", "sp", "gp", "tp", "t0", "t1", "t2", + "s0", "s1", "a0", "a1", "a2", "a3", "a4", "a5", "a6", "a7", + "s2", "s3", "s4", "s5", "s6", "s7", "s8", "s9", "s10", "s11", + "t3", "t4", "t5", "t6"]; + f.debug_map().entries(REG_NAME.iter().zip(self.0)).finish() + } + } + f.debug_struct("TrapFrame") + .field("regs", &Regs(&self.x)) + .field("sstatus", &self.sstatus) + .field("sepc", &self.sepc) + .field("stval", &self.stval) + .field("scause", &self.scause.cause()) + .finish() + } +} + +/// Kernel stack contents for a new thread +#[derive(Debug)] +#[repr(C)] +pub struct InitStack { + context: ContextData, + tf: TrapFrame, +} + +impl InitStack { + /// Push the InitStack on the stack and transfer to a Context. + unsafe fn push_at(self, stack_top: usize) -> Context { + let ptr = (stack_top as *mut Self).sub(1); //real kernel stack top + *ptr = self; + Context { sp: ptr as usize } + } +} + +extern { + fn trap_return(); +} + +/// Saved registers for kernel context switches. +#[derive(Debug, Default)] +#[repr(C)] +struct ContextData { + /// Return address + ra: usize, + /// Page table token + satp: usize, + /// Callee-saved registers + s: [usize; 12], +} + +impl ContextData { + fn new(satp: usize) -> Self { + ContextData { ra: trap_return as usize, satp, ..ContextData::default() } + } +} + +/// Context of a kernel thread. +#[derive(Debug)] +#[repr(C)] +pub struct Context { + /// The stack pointer of the suspended thread. + /// A `ContextData` is stored here. + sp: usize, +} + +impl Context { + /// Switch to another kernel thread. + /// + /// Push all callee-saved registers at the current kernel stack. + /// Store current sp, switch to target. + /// Pop all callee-saved registers, then return to the target. + #[naked] + #[inline(never)] + pub unsafe extern fn switch(&mut self, _target: &mut Self) { + #[cfg(target_arch = "riscv32")] + asm!(r" + .equ XLENB, 4 + .macro Load reg, mem + lw \reg, \mem + .endm + .macro Store reg, mem + sw \reg, \mem + .endm"); + #[cfg(target_arch = "riscv64")] + asm!(r" + .equ XLENB, 8 + .macro Load reg, mem + ld \reg, \mem + .endm + .macro Store reg, mem + sd \reg, \mem + .endm"); + asm!(" + // save from's registers + addi sp, sp, (-XLENB*14) + Store sp, 0(a0) + Store ra, 0*XLENB(sp) + Store s0, 2*XLENB(sp) + Store s1, 3*XLENB(sp) + Store s2, 4*XLENB(sp) + Store s3, 5*XLENB(sp) + Store s4, 6*XLENB(sp) + Store s5, 7*XLENB(sp) + Store s6, 8*XLENB(sp) + Store s7, 9*XLENB(sp) + Store s8, 10*XLENB(sp) + Store s9, 11*XLENB(sp) + Store s10, 12*XLENB(sp) + Store s11, 13*XLENB(sp) + csrr s11, satp + Store s11, 1*XLENB(sp) + + // restore to's registers + Load sp, 0(a1) + Load s11, 1*XLENB(sp) + csrw satp, s11 + Load ra, 0*XLENB(sp) + Load s0, 2*XLENB(sp) + Load s1, 3*XLENB(sp) + Load s2, 4*XLENB(sp) + Load s3, 5*XLENB(sp) + Load s4, 6*XLENB(sp) + Load s5, 7*XLENB(sp) + Load s6, 8*XLENB(sp) + Load s7, 9*XLENB(sp) + Load s8, 10*XLENB(sp) + Load s9, 11*XLENB(sp) + Load s10, 12*XLENB(sp) + Load s11, 13*XLENB(sp) + addi sp, sp, (XLENB*14) + + Store zero, 0(a1) + ret" + : : : : "volatile" ) + } + + /// Constructs a null Context for the current running thread. + pub unsafe fn null() -> Self { + Context { sp: 0 } + } + + /// Constructs Context for a new kernel thread. + /// + /// The new thread starts at function `entry` with an usize argument `arg`. + /// The stack pointer will be set to `kstack_top`. + /// The SATP register will be set to `satp`. + pub unsafe fn new_kernel_thread(entry: extern fn(usize) -> !, arg: usize, kstack_top: usize, satp: usize) -> Self { + InitStack { + context: ContextData::new(satp), + tf: TrapFrame::new_kernel_thread(entry, arg, kstack_top), + }.push_at(kstack_top) + } + + /// Constructs Context for a new user thread. + /// + /// The new thread starts at `entry_addr`. + /// The stack pointer of user and kernel mode will be set to `ustack_top`, `kstack_top`. + /// The SATP register will be set to `satp`. + pub unsafe fn new_user_thread(entry_addr: usize, ustack_top: usize, kstack_top: usize, _is32: bool, satp: usize) -> Self { + InitStack { + context: ContextData::new(satp), + tf: TrapFrame::new_user_thread(entry_addr, ustack_top), + }.push_at(kstack_top) + } + + /// Fork a user process and get the new Context. + /// + /// The stack pointer in kernel mode will be set to `kstack_top`. + /// The SATP register will be set to `satp`. + /// All the other registers are same as the original. + pub unsafe fn new_fork(tf: &TrapFrame, kstack_top: usize, satp: usize) -> Self { + InitStack { + context: ContextData::new(satp), + tf: { + let mut tf = tf.clone(); + // fork function's ret value, the new process is 0 + tf.x[10] = 0; // a0 + tf + }, + }.push_at(kstack_top) + } + + /// Fork a user thread and get the new Context. + /// + /// The stack pointer in kernel mode will be set to `kstack_top`. + /// The SATP register will be set to `satp`. + /// The new user stack will be set to `ustack_top`. + /// The new thread pointer will be set to `tls`. + /// All the other registers are same as the original. + pub unsafe fn new_clone(tf: &TrapFrame, ustack_top: usize, kstack_top: usize, satp: usize, tls: usize) -> Self { + InitStack { + context: ContextData::new(satp), + tf: { + let mut tf = tf.clone(); + tf.x[2] = ustack_top; // sp + tf.x[4] = tls; // tp + tf.x[10] = 0; // a0 + tf + }, + }.push_at(kstack_top) + } + + /// Used for getting the init TrapFrame of a new user context in `sys_exec`. + pub unsafe fn get_init_tf(&self) -> TrapFrame { + (*(self.sp as *const InitStack)).tf.clone() + } +} diff --git a/kernel/src/arch/mipsel/cpu.rs b/kernel/src/arch/mipsel/cpu.rs new file mode 100644 index 0000000..dea1df9 --- /dev/null +++ b/kernel/src/arch/mipsel/cpu.rs @@ -0,0 +1,38 @@ +use crate::consts::MAX_CPU_NUM; +use core::ptr::{read_volatile, write_volatile}; + +static mut STARTED: [bool; MAX_CPU_NUM] = [false; MAX_CPU_NUM]; + +pub unsafe fn set_cpu_id(cpu_id: usize) { + asm!("mv gp, $0" : : "r"(cpu_id)); +} + +pub fn id() -> usize { + let cpu_id; + unsafe { asm!("mv $0, gp" : "=r"(cpu_id)); } + cpu_id +} + +pub fn send_ipi(cpu_id: usize) { + super::sbi::send_ipi(1 << cpu_id); +} + +pub unsafe fn has_started(cpu_id: usize) -> bool { + read_volatile(&STARTED[cpu_id]) +} + +pub unsafe fn start_others(hart_mask: usize) { + for cpu_id in 0..MAX_CPU_NUM { + if (hart_mask >> cpu_id) & 1 != 0 { + write_volatile(&mut STARTED[cpu_id], true); + } + } +} + +pub fn halt() { + unsafe { riscv::asm::wfi() } +} + +pub unsafe fn exit_in_qemu(error_code: u8) -> ! { + super::sbi::shutdown() +} diff --git a/kernel/src/arch/mipsel/interrupt.rs b/kernel/src/arch/mipsel/interrupt.rs new file mode 100644 index 0000000..9488234 --- /dev/null +++ b/kernel/src/arch/mipsel/interrupt.rs @@ -0,0 +1,127 @@ +use mips::interrupts::*; +use crate::drivers::DRIVERS; +pub use self::context::*; +use log::*; + +#[path = "context.rs"] +mod context; + +/// Initialize interrupt +pub fn init() { + // extern { + // fn trap_entry(); + // } + // unsafe { + // // Set sscratch register to 0, indicating to exception vector that we are + // // presently executing in the kernel + // sscratch::write(0); + // // Set the exception vector address + // stvec::write(trap_entry as usize, stvec::TrapMode::Direct); + // // Enable IPI + // sie::set_ssoft(); + // // Enable external interrupt + // if super::cpu::id() == super::BOOT_HART_ID { + // sie::set_sext(); + // } + // } + // info!("interrupt: init end"); +} + +/// Enable interrupt +#[inline] +pub unsafe fn enable() { + // sstatus::set_sie(); +} + +/// Disable interrupt and return current interrupt status +#[inline] +pub unsafe fn disable_and_store() -> usize { + // let e = sstatus::read().sie() as usize; + // sstatus::clear_sie(); + // e +} + +/// Enable interrupt if `flags` != 0 +#[inline] +pub unsafe fn restore(flags: usize) { + // if flags != 0 { + // enable(); + // } +} + +/// Dispatch and handle interrupt. +/// +/// This function is called from `trap.asm`. +#[no_mangle] +pub extern fn rust_trap(tf: &mut TrapFrame) { + // use self::scause::{Trap, Interrupt as I, Exception as E}; + // trace!("Interrupt @ CPU{}: {:?} ", super::cpu::id(), tf.scause.cause()); + // match tf.scause.cause() { + // Trap::Interrupt(I::SupervisorExternal) => external(), + // Trap::Interrupt(I::SupervisorSoft) => ipi(), + // Trap::Interrupt(I::SupervisorTimer) => timer(), + // Trap::Exception(E::UserEnvCall) => syscall(tf), + // Trap::Exception(E::LoadPageFault) => page_fault(tf), + // Trap::Exception(E::StorePageFault) => page_fault(tf), + // Trap::Exception(E::InstructionPageFault) => page_fault(tf), + // _ => crate::trap::error(tf), + // } + // trace!("Interrupt end"); +} + +fn external() { + #[cfg(feature = "board_u540")] + unsafe { super::board::handle_external_interrupt(); } + + // true means handled, false otherwise + let handlers = [try_process_serial, try_process_drivers]; + for handler in handlers.iter() { + if handler() == true { + break + } + } +} + +fn try_process_serial() -> bool { + match super::io::getchar_option() { + Some(ch) => { + crate::trap::serial(ch); + true + } + None => false + } +} + +fn try_process_drivers() -> bool { + for driver in DRIVERS.read().iter() { + if driver.try_handle_interrupt(None) == true { + return true + } + } + return false +} + +fn ipi() { + debug!("IPI"); + super::sbi::clear_ipi(); +} + +fn timer() { + super::timer::set_next(); + crate::trap::timer(); +} + +fn syscall(tf: &mut TrapFrame) { + tf.sepc += 4; // Must before syscall, because of fork. + let ret = crate::syscall::syscall(tf.x[17], [tf.x[10], tf.x[11], tf.x[12], tf.x[13], tf.x[14], tf.x[15]], tf); + tf.x[10] = ret as usize; +} + +fn page_fault(tf: &mut TrapFrame) { + let addr = tf.stval; + trace!("\nEXCEPTION: Page Fault @ {:#x}", addr); + + if !crate::memory::handle_page_fault(addr) { + crate::trap::error(tf); + } +} diff --git a/kernel/src/arch/mipsel/io.rs b/kernel/src/arch/mipsel/io.rs new file mode 100644 index 0000000..5f405ee --- /dev/null +++ b/kernel/src/arch/mipsel/io.rs @@ -0,0 +1,52 @@ +use core::fmt::{Write, Result, Arguments}; +use super::sbi; + +struct SerialPort; + +impl Write for SerialPort { + fn write_str(&mut self, s: &str) -> Result { + for c in s.bytes() { + if c == 127 { + putchar(8); + putchar(b' '); + putchar(8); + } else { + putchar(c); + } + } + Ok(()) + } +} + +fn putchar(c: u8) { + if cfg!(feature = "board_u540") { + if c == b'\n' { + sbi::console_putchar(b'\r' as usize); + } + } + sbi::console_putchar(c as usize); +} + +pub fn getchar() -> char { + let c = sbi::console_getchar() as u8; + + match c { + 255 => '\0', // null + c => c as char, + } +} + +pub fn getchar_option() -> Option { + let c = sbi::console_getchar() as isize; + match c { + -1 => None, + c => Some(c as u8 as char), + } +} + +pub fn putfmt(fmt: Arguments) { + SerialPort.write_fmt(fmt).unwrap(); +} + +const TXDATA: *mut u32 = 0x38000000 as *mut u32; +const RXDATA: *mut u32 = 0x38000004 as *mut u32; diff --git a/kernel/src/arch/mipsel/memory.rs b/kernel/src/arch/mipsel/memory.rs new file mode 100644 index 0000000..79ba0d3 --- /dev/null +++ b/kernel/src/arch/mipsel/memory.rs @@ -0,0 +1,93 @@ +use core::mem; +use riscv::{addr::*, register::sstatus}; +use rcore_memory::PAGE_SIZE; +use log::*; +use crate::memory::{FRAME_ALLOCATOR, init_heap, MemoryAttr, MemorySet, Linear}; +use crate::consts::{MEMORY_OFFSET, MEMORY_END, KERNEL_OFFSET}; +use riscv::register::satp; + +/// Initialize the memory management module +pub fn init(dtb: usize) { + unsafe { sstatus::set_sum(); } // Allow user memory access + // initialize heap and Frame allocator + init_frame_allocator(); + init_heap(); + // remap the kernel use 4K page + remap_the_kernel(dtb); +} + +pub fn init_other() { + unsafe { + sstatus::set_sum(); // Allow user memory access + asm!("csrw satp, $0; sfence.vma" :: "r"(SATP) :: "volatile"); + } +} + +fn init_frame_allocator() { + use bit_allocator::BitAlloc; + use core::ops::Range; + + let mut ba = FRAME_ALLOCATOR.lock(); + let range = to_range((end as usize) - KERNEL_OFFSET + MEMORY_OFFSET + PAGE_SIZE, MEMORY_END); + ba.insert(range); + + info!("frame allocator: init end"); + + /// Transform memory area `[start, end)` to integer range for `FrameAllocator` + fn to_range(start: usize, end: usize) -> Range { + let page_start = (start - MEMORY_OFFSET) / PAGE_SIZE; + let page_end = (end - MEMORY_OFFSET - 1) / PAGE_SIZE + 1; + assert!(page_start < page_end, "illegal range for frame allocator"); + page_start..page_end + } +} + +/// Remap the kernel memory address with 4K page recorded in p1 page table +fn remap_the_kernel(dtb: usize) { + let offset = -(KERNEL_OFFSET as isize - MEMORY_OFFSET as isize); + let mut ms = MemorySet::new_bare(); + ms.push(stext as usize, etext as usize, MemoryAttr::default().execute().readonly(), Linear::new(offset), "text"); + ms.push(sdata as usize, edata as usize, MemoryAttr::default(), Linear::new(offset), "data"); + ms.push(srodata as usize, erodata as usize, MemoryAttr::default().readonly(), Linear::new(offset), "rodata"); + ms.push(bootstack as usize, bootstacktop as usize, MemoryAttr::default(), Linear::new(offset), "stack"); + ms.push(sbss as usize, ebss as usize, MemoryAttr::default(), Linear::new(offset), "bss"); + ms.push(dtb, dtb + super::consts::MAX_DTB_SIZE, MemoryAttr::default().readonly(), Linear::new(offset), "dts"); + // map PLIC for HiFiveU + let offset = -(KERNEL_OFFSET as isize); + ms.push(KERNEL_OFFSET + 0x0C00_2000, KERNEL_OFFSET + 0x0C00_2000 + PAGE_SIZE, MemoryAttr::default(), Linear::new(offset), "plic0"); + ms.push(KERNEL_OFFSET + 0x0C20_2000, KERNEL_OFFSET + 0x0C20_2000 + PAGE_SIZE, MemoryAttr::default(), Linear::new(offset), "plic1"); + unsafe { ms.activate(); } + unsafe { SATP = ms.token(); } + mem::forget(ms); + info!("remap kernel end"); +} + +// First core stores its SATP here. +// Other cores load it later. +static mut SATP: usize = 0; + +pub unsafe fn clear_bss() { + let start = sbss as usize; + let end = ebss as usize; + let step = core::mem::size_of::(); + for i in (start..end).step_by(step) { + (i as *mut usize).write(0); + } +} + +// Symbols provided by linker script +#[allow(dead_code)] +extern { + fn stext(); + fn etext(); + fn sdata(); + fn edata(); + fn srodata(); + fn erodata(); + fn sbss(); + fn ebss(); + fn start(); + fn end(); + fn bootstack(); + fn bootstacktop(); +} diff --git a/kernel/src/arch/mipsel/mod.rs b/kernel/src/arch/mipsel/mod.rs new file mode 100644 index 0000000..bdd6d6f --- /dev/null +++ b/kernel/src/arch/mipsel/mod.rs @@ -0,0 +1,88 @@ +pub mod io; +pub mod interrupt; +pub mod timer; +pub mod paging; +pub mod memory; +pub mod compiler_rt; +pub mod consts; +pub mod cpu; +pub mod syscall; +pub mod rand; +#[cfg(feature = "board_u540")] +#[path = "board/u540/mod.rs"] +mod board; +mod sbi; + +use log::*; + +#[no_mangle] +pub extern fn rust_main(hartid: usize, dtb: usize, hart_mask: usize) -> ! { + // An initial recursive page table has been set by BBL (shared by all cores) + + unsafe { cpu::set_cpu_id(hartid); } + + if hartid != BOOT_HART_ID { + while unsafe { !cpu::has_started(hartid) } { } + println!("Hello RISCV! in hart {}, dtb @ {:#x}", hartid, dtb); + others_main(); + //other_main -> ! + } + + unsafe { memory::clear_bss(); } + + println!("Hello RISCV! in hart {}, dtb @ {:#x}", hartid, dtb); + + crate::logging::init(); + interrupt::init(); + memory::init(dtb); + timer::init(); + // FIXME: init driver on u540 + #[cfg(not(feature = "board_u540"))] + crate::drivers::init(dtb); + #[cfg(feature = "board_u540")] + unsafe { board::init_external_interrupt(); } + crate::process::init(); + + unsafe { cpu::start_others(hart_mask); } + crate::kmain(); +} + +fn others_main() -> ! { + interrupt::init(); + memory::init_other(); + timer::init(); + crate::kmain(); +} + +#[cfg(not(feature = "board_u540"))] +const BOOT_HART_ID: usize = 0; +#[cfg(feature = "board_u540")] +const BOOT_HART_ID: usize = 1; + +/// Constant & Macro for `trap.asm` +#[cfg(target_arch = "riscv32")] +global_asm!(r" + .equ XLENB, 4 + .equ XLENb, 32 + .macro LOAD a1, a2 + lw \a1, \a2*XLENB(sp) + .endm + .macro STORE a1, a2 + sw \a1, \a2*XLENB(sp) + .endm +"); +#[cfg(target_arch = "riscv64")] +global_asm!(r" + .equ XLENB, 8 + .equ XLENb, 64 + .macro LOAD a1, a2 + ld \a1, \a2*XLENB(sp) + .endm + .macro STORE a1, a2 + sd \a1, \a2*XLENB(sp) + .endm +"); + + +global_asm!(include_str!("boot/entry.asm")); +global_asm!(include_str!("boot/trap.asm")); diff --git a/kernel/src/arch/mipsel/paging.rs b/kernel/src/arch/mipsel/paging.rs new file mode 100644 index 0000000..a392865 --- /dev/null +++ b/kernel/src/arch/mipsel/paging.rs @@ -0,0 +1,253 @@ +use crate::consts::RECURSIVE_INDEX; +// Depends on kernel +use crate::memory::{active_table, alloc_frame, dealloc_frame}; +use riscv::addr::*; +use riscv::asm::{sfence_vma, sfence_vma_all}; +use riscv::paging::{Mapper, PageTable as RvPageTable, PageTableEntry, PageTableFlags as EF, RecursivePageTable, PageTableType}; +use riscv::paging::{FrameAllocator, FrameDeallocator}; +use riscv::register::satp; +use rcore_memory::paging::*; +use log::*; +#[cfg(target_arch = "riscv32")] +use crate::consts::KERNEL_P2_INDEX; +#[cfg(target_arch = "riscv64")] +use crate::consts::KERNEL_P4_INDEX; + +pub struct ActivePageTable(RecursivePageTable<'static>, PageEntry); + +/// PageTableEntry: the contents of this entry. +/// Page: this entry is the pte of page `Page`. +pub struct PageEntry(&'static mut PageTableEntry, Page); + +impl PageTable for ActivePageTable { + + fn map(&mut self, addr: usize, target: usize) -> &mut Entry { + // use riscv::paging:Mapper::map_to, + // map the 4K `page` to the 4K `frame` with `flags` + let flags = EF::VALID | EF::READABLE | EF::WRITABLE; + let page = Page::of_addr(VirtAddr::new(addr)); + let frame = Frame::of_addr(PhysAddr::new(target)); + // map the page to the frame using FrameAllocatorForRiscv + // we may need frame allocator to alloc frame for new page table(first/second) + self.0.map_to(page, frame, flags, &mut FrameAllocatorForRiscv).unwrap().flush(); + self.get_entry(addr).expect("fail to get entry") + } + + fn unmap(&mut self, addr: usize) { + let page = Page::of_addr(VirtAddr::new(addr)); + let (_, flush) = self.0.unmap(page).unwrap(); + flush.flush(); + } + + fn get_entry(&mut self, vaddr: usize) -> Option<&mut Entry> { + let page = Page::of_addr(VirtAddr::new(vaddr)); + if let Ok(e) = self.0.ref_entry(page.clone()) { + let e = unsafe { &mut *(e as *mut PageTableEntry) }; + self.1 = PageEntry(e, page); + Some(&mut self.1 as &mut Entry) + } else { + None + } + } +} + +impl PageTableExt for ActivePageTable {} + +/// The virtual address of root page table +#[cfg(target_arch = "riscv32")] +const ROOT_PAGE_TABLE: *mut RvPageTable = + ((RECURSIVE_INDEX << 12 << 10) | + ((RECURSIVE_INDEX+1) << 12)) as *mut RvPageTable; +#[cfg(all(target_arch = "riscv64", feature = "sv39"))] +const ROOT_PAGE_TABLE: *mut RvPageTable = + ((0xFFFF_0000_0000_0000) | + (0o777 << 12 << 9 << 9 << 9) | + (RECURSIVE_INDEX << 12 << 9 << 9) | + (RECURSIVE_INDEX << 12 << 9) | + ((RECURSIVE_INDEX+1) << 12)) as *mut RvPageTable; +#[cfg(all(target_arch = "riscv64", not(feature = "sv39")))] +const ROOT_PAGE_TABLE: *mut RvPageTable = + ((0xFFFF_0000_0000_0000) | + (RECURSIVE_INDEX << 12 << 9 << 9 << 9) | + (RECURSIVE_INDEX << 12 << 9 << 9) | + (RECURSIVE_INDEX << 12 << 9) | + ((RECURSIVE_INDEX+1) << 12)) as *mut RvPageTable; + +impl ActivePageTable { + #[cfg(target_arch = "riscv32")] + pub unsafe fn new() -> Self { + ActivePageTable( + RecursivePageTable::new(&mut *ROOT_PAGE_TABLE).unwrap(), + ::core::mem::uninitialized() + ) + } + #[cfg(target_arch = "riscv64")] + pub unsafe fn new() -> Self { + #[cfg(feature = "sv39")] + let type_ = PageTableType::Sv39; + #[cfg(not(feature = "sv39"))] + let type_ = PageTableType::Sv48; + ActivePageTable( + RecursivePageTable::new(&mut *ROOT_PAGE_TABLE, type_).unwrap(), + ::core::mem::uninitialized() + ) + } +} + +/// implementation for the Entry trait in /crate/memory/src/paging/mod.rs +impl Entry for PageEntry { + fn update(&mut self) { + unsafe { sfence_vma(0, self.1.start_address().as_usize()); } + } + fn accessed(&self) -> bool { self.0.flags().contains(EF::ACCESSED) } + fn dirty(&self) -> bool { self.0.flags().contains(EF::DIRTY) } + fn writable(&self) -> bool { self.0.flags().contains(EF::WRITABLE) } + fn present(&self) -> bool { self.0.flags().contains(EF::VALID | EF::READABLE) } + fn clear_accessed(&mut self) { self.0.flags_mut().remove(EF::ACCESSED); } + fn clear_dirty(&mut self) { self.0.flags_mut().remove(EF::DIRTY); } + fn set_writable(&mut self, value: bool) { self.0.flags_mut().set(EF::WRITABLE, value); } + fn set_present(&mut self, value: bool) { self.0.flags_mut().set(EF::VALID | EF::READABLE, value); } + fn target(&self) -> usize { self.0.addr().as_usize() } + fn set_target(&mut self, target: usize) { + let flags = self.0.flags(); + let frame = Frame::of_addr(PhysAddr::new(target)); + self.0.set(frame, flags); + } + fn writable_shared(&self) -> bool { self.0.flags().contains(EF::RESERVED1) } + fn readonly_shared(&self) -> bool { self.0.flags().contains(EF::RESERVED2) } + fn set_shared(&mut self, writable: bool) { + let flags = self.0.flags_mut(); + flags.set(EF::RESERVED1, writable); + flags.set(EF::RESERVED2, !writable); + } + fn clear_shared(&mut self) { self.0.flags_mut().remove(EF::RESERVED1 | EF::RESERVED2); } + fn swapped(&self) -> bool { self.0.flags().contains(EF::RESERVED1) } + fn set_swapped(&mut self, value: bool) { self.0.flags_mut().set(EF::RESERVED1, value); } + fn user(&self) -> bool { self.0.flags().contains(EF::USER) } + fn set_user(&mut self, value: bool) { self.0.flags_mut().set(EF::USER, value); } + fn execute(&self) -> bool { self.0.flags().contains(EF::EXECUTABLE) } + fn set_execute(&mut self, value: bool) { self.0.flags_mut().set(EF::EXECUTABLE, value); } + fn mmio(&self) -> u8 { 0 } + fn set_mmio(&mut self, _value: u8) { } +} + +#[derive(Debug)] +pub struct InactivePageTable0 { + root_frame: Frame, +} + +impl InactivePageTable for InactivePageTable0 { + type Active = ActivePageTable; + + fn new_bare() -> Self { + let target = alloc_frame().expect("failed to allocate frame"); + let frame = Frame::of_addr(PhysAddr::new(target)); + active_table().with_temporary_map(target, |_, table: &mut RvPageTable| { + table.zero(); + table.set_recursive(RECURSIVE_INDEX, frame.clone()); + }); + InactivePageTable0 { root_frame: frame } + } + + #[cfg(target_arch = "riscv32")] + fn map_kernel(&mut self) { + let table = unsafe { &mut *ROOT_PAGE_TABLE }; + extern { + fn start(); + fn end(); + } + let mut entrys: [PageTableEntry; 16] = unsafe { core::mem::uninitialized() }; + let entry_start = start as usize >> 22; + let entry_end = (end as usize >> 22) + 1; + let entry_count = entry_end - entry_start; + for i in 0..entry_count { + entrys[i] = table[entry_start + i]; + } + + self.edit(|_| { + // NOTE: 'table' now refers to new page table + for i in 0..entry_count { + table[entry_start + i] = entrys[i]; + } + }); + } + + #[cfg(target_arch = "riscv64")] + fn map_kernel(&mut self) { + let table = unsafe { &mut *ROOT_PAGE_TABLE }; + let e1 = table[KERNEL_P4_INDEX]; + assert!(!e1.is_unused()); + + self.edit(|_| { + table[KERNEL_P4_INDEX] = e1; + }); + } + + #[cfg(target_arch = "riscv32")] + fn token(&self) -> usize { + self.root_frame.number() | (1 << 31) // as satp + } + #[cfg(target_arch = "riscv64")] + fn token(&self) -> usize { + use bit_field::BitField; + let mut satp = self.root_frame.number(); + satp.set_bits(44..60, 0); // AS is 0 + #[cfg(feature = "sv39")] + satp.set_bits(60..64, satp::Mode::Sv39 as usize); + #[cfg(not(feature = "sv39"))] + satp.set_bits(60..64, satp::Mode::Sv48 as usize); + satp + } + + unsafe fn set_token(token: usize) { + asm!("csrw satp, $0" :: "r"(token) :: "volatile"); + } + + fn active_token() -> usize { + satp::read().bits() + } + + fn flush_tlb() { + unsafe { sfence_vma_all(); } + } + + fn edit(&mut self, f: impl FnOnce(&mut Self::Active) -> T) -> T { + let target = satp::read().frame().start_address().as_usize(); + active_table().with_temporary_map(target, |active_table, root_table: &mut RvPageTable| { + let backup = root_table[RECURSIVE_INDEX].clone(); + + // overwrite recursive mapping + root_table[RECURSIVE_INDEX].set(self.root_frame.clone(), EF::VALID); + unsafe { sfence_vma_all(); } + + // execute f in the new context + let ret = f(active_table); + + // restore recursive mapping to original p2 table + root_table[RECURSIVE_INDEX] = backup; + unsafe { sfence_vma_all(); } + + ret + }) + } +} + +impl Drop for InactivePageTable0 { + fn drop(&mut self) { + dealloc_frame(self.root_frame.start_address().as_usize()); + } +} + +struct FrameAllocatorForRiscv; + +impl FrameAllocator for FrameAllocatorForRiscv { + fn alloc(&mut self) -> Option { + alloc_frame().map(|addr| Frame::of_addr(PhysAddr::new(addr))) + } +} + +impl FrameDeallocator for FrameAllocatorForRiscv { + fn dealloc(&mut self, frame: Frame) { + dealloc_frame(frame.start_address().as_usize()); + } +} diff --git a/kernel/src/arch/mipsel/rand.rs b/kernel/src/arch/mipsel/rand.rs new file mode 100644 index 0000000..7395793 --- /dev/null +++ b/kernel/src/arch/mipsel/rand.rs @@ -0,0 +1,3 @@ +pub fn rand() -> u64 { + return 0; +} \ No newline at end of file diff --git a/kernel/src/arch/mipsel/sbi.rs b/kernel/src/arch/mipsel/sbi.rs new file mode 100644 index 0000000..0357642 --- /dev/null +++ b/kernel/src/arch/mipsel/sbi.rs @@ -0,0 +1,64 @@ +//! Port from sbi.h + +#[inline(always)] +fn sbi_call(which: usize, arg0: usize, arg1: usize, arg2: usize) -> usize { + let ret; + unsafe { + asm!("ecall" + : "={x10}" (ret) + : "{x10}" (arg0), "{x11}" (arg1), "{x12}" (arg2), "{x17}" (which) + : "memory" + : "volatile"); + } + ret +} + +pub fn console_putchar(ch: usize) { + sbi_call(SBI_CONSOLE_PUTCHAR, ch, 0, 0); +} + +pub fn console_getchar() -> usize { + sbi_call(SBI_CONSOLE_GETCHAR, 0, 0, 0) +} + +pub fn shutdown() -> ! { + sbi_call(SBI_SHUTDOWN, 0, 0, 0); + unreachable!() +} + +pub fn set_timer(stime_value: u64) { + #[cfg(target_pointer_width = "32")] + sbi_call(SBI_SET_TIMER, stime_value as usize, (stime_value >> 32) as usize, 0); + #[cfg(target_pointer_width = "64")] + sbi_call(SBI_SET_TIMER, stime_value as usize, 0, 0); +} + +pub fn clear_ipi() { + sbi_call(SBI_CLEAR_IPI, 0, 0, 0); +} + +pub fn send_ipi(hart_mask: usize) { + sbi_call(SBI_SEND_IPI, &hart_mask as *const _ as usize, 0, 0); +} + +pub fn remote_fence_i(hart_mask: usize) { + sbi_call(SBI_REMOTE_FENCE_I, &hart_mask as *const _ as usize, 0, 0); +} + +pub fn remote_sfence_vma(hart_mask: usize, _start: usize, _size: usize) { + sbi_call(SBI_REMOTE_SFENCE_VMA, &hart_mask as *const _ as usize, 0, 0); +} + +pub fn remote_sfence_vma_asid(hart_mask: usize, _start: usize, _size: usize, _asid: usize) { + sbi_call(SBI_REMOTE_SFENCE_VMA_ASID, &hart_mask as *const _ as usize, 0, 0); +} + +const SBI_SET_TIMER: usize = 0; +const SBI_CONSOLE_PUTCHAR: usize = 1; +const SBI_CONSOLE_GETCHAR: usize = 2; +const SBI_CLEAR_IPI: usize = 3; +const SBI_SEND_IPI: usize = 4; +const SBI_REMOTE_FENCE_I: usize = 5; +const SBI_REMOTE_SFENCE_VMA: usize = 6; +const SBI_REMOTE_SFENCE_VMA_ASID: usize = 7; +const SBI_SHUTDOWN: usize = 8; diff --git a/kernel/src/arch/mipsel/syscall.rs b/kernel/src/arch/mipsel/syscall.rs new file mode 100644 index 0000000..b1db116 --- /dev/null +++ b/kernel/src/arch/mipsel/syscall.rs @@ -0,0 +1,285 @@ +//! RISCV32 syscall ids +//! Reference: https://github.com/riscv/riscv-musl/blob/staging/arch/riscv32/bits/syscall.h.in + +pub const SYS_IO_SETUP: usize = 0; +pub const SYS_IO_DESTROY: usize = 1; +pub const SYS_IO_SUBMIT: usize = 2; +pub const SYS_IO_CANCEL: usize = 3; +pub const SYS_IO_GETEVENTS: usize = 4; +pub const SYS_SETXATTR: usize = 5; +pub const SYS_LSETXATTR: usize = 6; +pub const SYS_FSETXATTR: usize = 7; +pub const SYS_GETXATTR: usize = 8; +pub const SYS_LGETXATTR: usize = 9; +pub const SYS_FGETXATTR: usize = 10; +pub const SYS_LISTXATTR: usize = 11; +pub const SYS_LLISTXATTR: usize = 12; +pub const SYS_FLISTXATTR: usize = 13; +pub const SYS_REMOVEXATTR: usize = 14; +pub const SYS_LREMOVEXATTR: usize = 15; +pub const SYS_FREMOVEXATTR: usize = 16; +pub const SYS_GETCWD: usize = 17; +pub const SYS_LOOKUP_DCOOKIE: usize = 18; +pub const SYS_EVENTFD2: usize = 19; +pub const SYS_EPOLL_CREATE1: usize = 20; +pub const SYS_EPOLL_CTL: usize = 21; +pub const SYS_EPOLL_PWAIT: usize = 22; +pub const SYS_DUP: usize = 23; +pub const SYS_DUP3: usize = 24; +pub const SYS_FCNTL: usize = 25; +pub const SYS_INOTIFY_INIT1: usize = 26; +pub const SYS_INOTIFY_ADD_WATCH: usize = 27; +pub const SYS_INOTIFY_RM_WATCH: usize = 28; +pub const SYS_IOCTL: usize = 29; +pub const SYS_IOPRIO_SET: usize = 30; +pub const SYS_IOPRIO_GET: usize = 31; +pub const SYS_FLOCK: usize = 32; +pub const SYS_MKNODAT: usize = 33; +pub const SYS_MKDIRAT: usize = 34; +pub const SYS_UNLINKAT: usize = 35; +pub const SYS_SYMLINKAT: usize = 36; +pub const SYS_LINKAT: usize = 37; +pub const SYS_RENAMEAT: usize = 38; // FIXME +pub const SYS_UMOUNT2: usize = 39; +pub const SYS_MOUNT: usize = 40; +pub const SYS_PIVOT_ROOT: usize = 41; +pub const SYS_NFSSERVCTL: usize = 42; +pub const SYS_STATFS: usize = 43; +pub const SYS_FSTATFS: usize = 44; +pub const SYS_TRUNCATE: usize = 45; +pub const SYS_FTRUNCATE: usize = 46; +pub const SYS_FALLOCATE: usize = 47; +pub const SYS_FACCESSAT: usize = 48; +pub const SYS_CHDIR: usize = 49; +pub const SYS_FCHDIR: usize = 50; +pub const SYS_CHROOT: usize = 51; +pub const SYS_FCHMOD: usize = 52; +pub const SYS_FCHMODAT: usize = 53; +pub const SYS_FCHOWNAT: usize = 54; +pub const SYS_FCHOWN: usize = 55; +pub const SYS_OPENAT: usize = 56; +pub const SYS_CLOSE: usize = 57; +pub const SYS_VHANGUP: usize = 58; +pub const SYS_PIPE2: usize = 59; +pub const SYS_QUOTACTL: usize = 60; +pub const SYS_GETDENTS64: usize = 61; +pub const SYS_LSEEK: usize = 62; +pub const SYS_READ: usize = 63; +pub const SYS_WRITE: usize = 64; +pub const SYS_READV: usize = 65; +pub const SYS_WRITEV: usize = 66; +pub const SYS_PREAD64: usize = 67; +pub const SYS_PWRITE64: usize = 68; +pub const SYS_PREADV: usize = 69; +pub const SYS_PWRITEV: usize = 70; +pub const SYS_SENDFILE: usize = 71; +pub const SYS_PSELECT6: usize = 72; +pub const SYS_PPOLL: usize = 73; +pub const SYS_SIGNALFD4: usize = 74; +pub const SYS_VMSPLICE: usize = 75; +pub const SYS_SPLICE: usize = 76; +pub const SYS_TEE: usize = 77; +pub const SYS_READLINKAT: usize = 78; +pub const SYS_NEWFSTATAT: usize = 79; +pub const SYS_FSTAT: usize = 80; +pub const SYS_SYNC: usize = 81; +pub const SYS_FSYNC: usize = 82; +pub const SYS_FDATASYNC: usize = 83; +pub const SYS_SYNC_FILE_RANGE: usize = 84; +pub const SYS_TIMERFD_CREATE: usize = 85; +pub const SYS_TIMERFD_SETTIME: usize = 86; +pub const SYS_TIMERFD_GETTIME: usize = 87; +pub const SYS_UTIMENSAT: usize = 88; +pub const SYS_ACCT: usize = 89; +pub const SYS_CAPGET: usize = 90; +pub const SYS_CAPSET: usize = 91; +pub const SYS_PERSONALITY: usize = 92; +pub const SYS_EXIT: usize = 93; +pub const SYS_EXIT_GROUP: usize = 94; +pub const SYS_WAITID: usize = 95; +pub const SYS_SET_TID_ADDRESS: usize = 96; +pub const SYS_UNSHARE: usize = 97; +pub const SYS_FUTEX: usize = 98; +pub const SYS_SET_ROBUST_LIST: usize = 99; +pub const SYS_GET_ROBUST_LIST: usize = 100; +pub const SYS_NANOSLEEP: usize = 101; +pub const SYS_GETITIMER: usize = 102; +pub const SYS_SETITIMER: usize = 103; +pub const SYS_KEXEC_LOAD: usize = 104; +pub const SYS_INIT_MODULE: usize = 105; +pub const SYS_DELETE_MODULE: usize = 106; +pub const SYS_TIMER_CREATE: usize = 107; +pub const SYS_TIMER_GETTIME: usize = 108; +pub const SYS_TIMER_GETOVERRUN: usize = 109; +pub const SYS_TIMER_SETTIME: usize = 110; +pub const SYS_TIMER_DELETE: usize = 111; +pub const SYS_CLOCK_SETTIME: usize = 112; +pub const SYS_CLOCK_GETTIME: usize = 113; +pub const SYS_CLOCK_GETRES: usize = 114; +pub const SYS_CLOCK_NANOSLEEP: usize = 115; +pub const SYS_SYSLOG: usize = 116; +pub const SYS_PTRACE: usize = 117; +pub const SYS_SCHED_SETPARAM: usize = 118; +pub const SYS_SCHED_SETSCHEDULER: usize = 119; +pub const SYS_SCHED_GETSCHEDULER: usize = 120; +pub const SYS_SCHED_GETPARAM: usize = 121; +pub const SYS_SCHED_SETAFFINITY: usize = 122; +pub const SYS_SCHED_GETAFFINITY: usize = 123; +pub const SYS_SCHED_YIELD: usize = 124; +pub const SYS_SCHED_GET_PRIORITY_MAX: usize = 125; +pub const SYS_SCHED_GET_PRIORITY_MIN: usize = 126; +pub const SYS_SCHED_RR_GET_INTERVAL: usize = 127; +pub const SYS_RESTART_SYSCALL: usize = 128; +pub const SYS_KILL: usize = 129; +pub const SYS_TKILL: usize = 130; +pub const SYS_TGKILL: usize = 131; +pub const SYS_SIGALTSTACK: usize = 132; +pub const SYS_RT_SIGSUSPEND: usize = 133; +pub const SYS_RT_SIGACTION: usize = 134; +pub const SYS_RT_SIGPROCMASK: usize = 135; +pub const SYS_RT_SIGPENDING: usize = 136; +pub const SYS_RT_SIGTIMEDWAIT: usize = 137; +pub const SYS_RT_SIGQUEUEINFO: usize = 138; +pub const SYS_RT_SIGRETURN: usize = 139; +pub const SYS_SETPRIORITY: usize = 140; +pub const SYS_GETPRIORITY: usize = 141; +pub const SYS_REBOOT: usize = 142; +pub const SYS_SETREGID: usize = 143; +pub const SYS_SETGID: usize = 144; +pub const SYS_SETREUID: usize = 145; +pub const SYS_SETUID: usize = 146; +pub const SYS_SETRESUID: usize = 147; +pub const SYS_GETRESUID: usize = 148; +pub const SYS_SETRESGID: usize = 149; +pub const SYS_GETRESGID: usize = 150; +pub const SYS_SETFSUID: usize = 151; +pub const SYS_SETFSGID: usize = 152; +pub const SYS_TIMES: usize = 153; +pub const SYS_SETPGID: usize = 154; +pub const SYS_GETPGID: usize = 155; +pub const SYS_GETSID: usize = 156; +pub const SYS_SETSID: usize = 157; +pub const SYS_GETGROUPS: usize = 158; +pub const SYS_SETGROUPS: usize = 159; +pub const SYS_UNAME: usize = 160; +pub const SYS_SETHOSTNAME: usize = 161; +pub const SYS_SETDOMAINNAME: usize = 162; +pub const SYS_GETRLIMIT: usize = 163; +pub const SYS_SETRLIMIT: usize = 164; +pub const SYS_GETRUSAGE: usize = 165; +pub const SYS_UMASK: usize = 166; +pub const SYS_PRCTL: usize = 167; +pub const SYS_GETCPU: usize = 168; +pub const SYS_GETTIMEOFDAY: usize = 169; +pub const SYS_SETTIMEOFDAY: usize = 170; +pub const SYS_ADJTIMEX: usize = 171; +pub const SYS_GETPID: usize = 172; +pub const SYS_GETPPID: usize = 173; +pub const SYS_GETUID: usize = 174; +pub const SYS_GETEUID: usize = 175; +pub const SYS_GETGID: usize = 176; +pub const SYS_GETEGID: usize = 177; +pub const SYS_GETTID: usize = 178; +pub const SYS_SYSINFO: usize = 179; +pub const SYS_MQ_OPEN: usize = 180; +pub const SYS_MQ_UNLINK: usize = 181; +pub const SYS_MQ_TIMEDSEND: usize = 182; +pub const SYS_MQ_TIMEDRECEIVE: usize = 183; +pub const SYS_MQ_NOTIFY: usize = 184; +pub const SYS_MQ_GETSETATTR: usize = 185; +pub const SYS_MSGGET: usize = 186; +pub const SYS_MSGCTL: usize = 187; +pub const SYS_MSGRCV: usize = 188; +pub const SYS_MSGSND: usize = 189; +pub const SYS_SEMGET: usize = 190; +pub const SYS_SEMCTL: usize = 191; +pub const SYS_SEMTIMEDOP: usize = 192; +pub const SYS_SEMOP: usize = 193; +pub const SYS_SHMGET: usize = 194; +pub const SYS_SHMCTL: usize = 195; +pub const SYS_SHMAT: usize = 196; +pub const SYS_SHMDT: usize = 197; +pub const SYS_SOCKET: usize = 198; +pub const SYS_SOCKETPAIR: usize = 199; +pub const SYS_BIND: usize = 200; +pub const SYS_LISTEN: usize = 201; +pub const SYS_ACCEPT: usize = 202; +pub const SYS_CONNECT: usize = 203; +pub const SYS_GETSOCKNAME: usize = 204; +pub const SYS_GETPEERNAME: usize = 205; +pub const SYS_SENDTO: usize = 206; +pub const SYS_RECVFROM: usize = 207; +pub const SYS_SETSOCKOPT: usize = 208; +pub const SYS_GETSOCKOPT: usize = 209; +pub const SYS_SHUTDOWN: usize = 210; +pub const SYS_SENDMSG: usize = 211; +pub const SYS_RECVMSG: usize = 212; +pub const SYS_READAHEAD: usize = 213; +pub const SYS_BRK: usize = 214; +pub const SYS_MUNMAP: usize = 215; +pub const SYS_MREMAP: usize = 216; +pub const SYS_ADD_KEY: usize = 217; +pub const SYS_REQUEST_KEY: usize = 218; +pub const SYS_KEYCTL: usize = 219; +pub const SYS_CLONE: usize = 220; +pub const SYS_EXECVE: usize = 221; +pub const SYS_MMAP: usize = 222; +pub const SYS_FADVISE64: usize = 223; +pub const SYS_SWAPON: usize = 224; +pub const SYS_SWAPOFF: usize = 225; +pub const SYS_MPROTECT: usize = 226; +pub const SYS_MSYNC: usize = 227; +pub const SYS_MLOCK: usize = 228; +pub const SYS_MUNLOCK: usize = 229; +pub const SYS_MLOCKALL: usize = 230; +pub const SYS_MUNLOCKALL: usize = 231; +pub const SYS_MINCORE: usize = 232; +pub const SYS_MADVISE: usize = 233; +pub const SYS_REMAP_FILE_PAGES: usize = 234; +pub const SYS_MBIND: usize = 235; +pub const SYS_GET_MEMPOLICY: usize = 236; +pub const SYS_SET_MEMPOLICY: usize = 237; +pub const SYS_MIGRATE_PAGES: usize = 238; +pub const SYS_MOVE_PAGES: usize = 239; +pub const SYS_RT_TGSIGQUEUEINFO: usize = 240; +pub const SYS_PERF_EVENT_OPEN: usize = 241; +pub const SYS_ACCEPT4: usize = 242; +pub const SYS_RECVMMSG: usize = 243; +pub const SYS_ARCH_SPECIFIC_SYSCALL: usize = 244; +pub const SYS_WAIT4: usize = 260; +pub const SYS_PRLIMIT64: usize = 261; +pub const SYS_FANOTIFY_INIT: usize = 262; +pub const SYS_FANOTIFY_MARK: usize = 263; +pub const SYS_NAME_TO_HANDLE_AT: usize = 264; +pub const SYS_OPEN_BY_HANDLE_AT: usize = 265; +pub const SYS_CLOCK_ADJTIME: usize = 266; +pub const SYS_SYNCFS: usize = 267; +pub const SYS_SETNS: usize = 268; +pub const SYS_SENDMMSG: usize = 269; +pub const SYS_PROCESS_VM_READV: usize = 270; +pub const SYS_PROCESS_VM_WRITEV: usize = 271; +pub const SYS_KCMP: usize = 272; +pub const SYS_FINIT_MODULE: usize = 273; +pub const SYS_SCHED_SETATTR: usize = 274; +pub const SYS_SCHED_GETATTR: usize = 275; +pub const SYS_RENAMEAT2: usize = 276; +pub const SYS_SECCOMP: usize = 277; +pub const SYS_GETRANDOM: usize = 278; +pub const SYS_MEMFD_CREATE: usize = 279; +pub const SYS_BPF: usize = 280; +pub const SYS_EXECVEAT: usize = 281; +pub const SYS_USERFAULTFD: usize = 282; +pub const SYS_MEMBARRIER: usize = 283; +pub const SYS_MLOCK2: usize = 284; +pub const SYS_COPY_FILE_RANGE: usize = 285; +pub const SYS_PREADV2: usize = 286; +pub const SYS_PWRITEV2: usize = 287; +pub const SYS_PKEY_MPROTECT: usize = 288; +pub const SYS_PKEY_ALLOC: usize = 289; +pub const SYS_PKEY_FREE: usize = 290; +pub const SYS_SYSRISCV: usize = SYS_ARCH_SPECIFIC_SYSCALL; +pub const SYS_RISCV_FLUSH_ICACHE: usize = SYS_SYSRISCV + 15; + +// custom temporary syscall +pub const SYS_MAP_PCI_DEVICE: usize = 999; +pub const SYS_GET_PADDR: usize = 998; diff --git a/kernel/src/arch/mipsel/timer.rs b/kernel/src/arch/mipsel/timer.rs new file mode 100644 index 0000000..8f10c73 --- /dev/null +++ b/kernel/src/arch/mipsel/timer.rs @@ -0,0 +1,40 @@ +use riscv::register::*; +use super::sbi; +use log::*; + +#[cfg(target_pointer_width = "64")] +pub fn get_cycle() -> u64 { + time::read() as u64 +} + +#[cfg(target_pointer_width = "32")] +pub fn get_cycle() -> u64 { + loop { + let hi = timeh::read(); + let lo = time::read(); + let tmp = timeh::read(); + if hi == tmp { + return ((hi as u64) << 32) | (lo as u64); + } + } +} + +pub fn read_epoch() -> u64 { + // TODO: support RTC + 0 +} + +/// Enable timer interrupt +pub fn init() { + // Enable supervisor timer interrupt + unsafe { sie::set_stimer(); } + set_next(); + info!("timer: init end"); +} + +/// Set the next timer interrupt +pub fn set_next() { + // 100Hz @ QEMU + let timebase = 250000; + sbi::set_timer(get_cycle() + timebase); +} diff --git a/kernel/targets/mipsel.json b/kernel/targets/mipsel.json new file mode 100644 index 0000000..346e3e8 --- /dev/null +++ b/kernel/targets/mipsel.json @@ -0,0 +1,36 @@ +{ + "arch": "mips", + "cpu": "mips32r2", + "llvm-target": "mipsel-unknown-none", + "data-layout": "e-m:m-p:32:32-i8:8:32-i16:16:32-i64:64-n32-S64", + "target-endian": "little", + "target-pointer-width": "32", + "target-c-int-width": "32", + "os": "none", + "features": "+mips32r2,+soft-float", + "max-atomic-width": "32", + "linker": "rust-lld", + "linker-flavor": "ld.lld", + "pre-link-args": { + "ld.lld": [ + "-Tsrc/arch/mipsel/boot/linker.ld" + ] + }, + "executables": true, + "panic-strategy": "abort", + "relocation-model": "static", + "abi-blacklist": [ + "cdecl", + "stdcall", + "fastcall", + "vectorcall", + "thiscall", + "aapcs", + "win64", + "sysv64", + "ptx-kernel", + "msp430-interrupt", + "x86-interrupt" + ], + "eliminate-frame-pointer": false +} From e53b3c16f6a38affdf650d62b606afbdc776a8dd Mon Sep 17 00:00:00 2001 From: Yuhao Zhou Date: Sun, 31 Mar 2019 23:31:37 +0800 Subject: [PATCH 02/85] Add interrupt for mips32 in crate::thread. --- crate/thread/src/interrupt.rs | 29 +++++++++++++++++++++++++++++ kernel/build.rs | 2 ++ kernel/src/arch/mipsel/mod.rs | 2 +- kernel/src/lib.rs | 4 ++++ 4 files changed, 36 insertions(+), 1 deletion(-) diff --git a/crate/thread/src/interrupt.rs b/crate/thread/src/interrupt.rs index d7c1d3c..cf8d382 100644 --- a/crate/thread/src/interrupt.rs +++ b/crate/thread/src/interrupt.rs @@ -61,3 +61,32 @@ pub unsafe fn restore(flags: usize) { pub unsafe fn enable_and_wfi() { asm!("msr daifclr, #2; wfi" :::: "volatile"); } + +#[inline(always)] +#[cfg(target_arch = "mips")] +pub unsafe fn disable_and_store() -> usize { + let cp0_status: usize; + asm!("mfc0 $0, $$12;" : "=r"(cp0_status) ::: "volatile"); + let cp0_status_new = cp0_status & !1; + asm!("mtc0 $0, $$12;" : : "r"(cp0_status_new) :: "volatile"); + cp0_status & 1 +} + +#[inline(always)] +#[cfg(target_arch = "mips")] +pub unsafe fn restore(flags: usize) { + let cp0_status: usize; + asm!("mfc0 $0, $$12;" : "=r"(cp0_status) ::: "volatile"); + let cp0_status_new = cp0_status | flags; + asm!("mtc0 $0, $$12;" : : "r"(cp0_status_new) :: "volatile"); +} + +#[inline(always)] +#[cfg(target_arch = "mips")] +pub unsafe fn enable_and_wfi() { + let cp0_status: usize; + asm!("mfc0 $0, $$12;" : "=r"(cp0_status) ::: "volatile"); + let cp0_status_new = cp0_status | 1; + asm!("mtc0 $0, $$12; wait;" : : "r"(cp0_status_new) :: "volatile"); +} + diff --git a/kernel/build.rs b/kernel/build.rs index 6f94b3f..657f765 100644 --- a/kernel/build.rs +++ b/kernel/build.rs @@ -18,6 +18,8 @@ fn main() { } "riscv64" => { } + "mipsel" => { + } "aarch64" => { } _ => panic!("Unknown arch {}", arch), diff --git a/kernel/src/arch/mipsel/mod.rs b/kernel/src/arch/mipsel/mod.rs index bdd6d6f..212bdce 100644 --- a/kernel/src/arch/mipsel/mod.rs +++ b/kernel/src/arch/mipsel/mod.rs @@ -1,5 +1,5 @@ pub mod io; -pub mod interrupt; +//pub mod interrupt; pub mod timer; pub mod paging; pub mod memory; diff --git a/kernel/src/lib.rs b/kernel/src/lib.rs index 4a2487d..488e3d5 100644 --- a/kernel/src/lib.rs +++ b/kernel/src/lib.rs @@ -41,6 +41,10 @@ mod backtrace; #[path = "arch/x86_64/mod.rs"] pub mod arch; +#[cfg(target_arch = "mipsel")] +#[path = "arch/mipsel/mod.rs"] +pub mod arch; + #[cfg(any(target_arch = "riscv32", target_arch = "riscv64"))] #[path = "arch/riscv32/mod.rs"] pub mod arch; From cbb59d853b9dad3436c1fc20a8a4a6f490713279 Mon Sep 17 00:00:00 2001 From: Yuhao Zhou Date: Mon, 1 Apr 2019 11:37:14 +0800 Subject: [PATCH 03/85] Fix arch error in mips. --- kernel/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/src/lib.rs b/kernel/src/lib.rs index 488e3d5..bc38154 100644 --- a/kernel/src/lib.rs +++ b/kernel/src/lib.rs @@ -41,7 +41,7 @@ mod backtrace; #[path = "arch/x86_64/mod.rs"] pub mod arch; -#[cfg(target_arch = "mipsel")] +#[cfg(target_arch = "mips")] #[path = "arch/mipsel/mod.rs"] pub mod arch; From 95b9fe5f5b17460f33a09dd268f1114a93d64db2 Mon Sep 17 00:00:00 2001 From: Yuhao Zhou Date: Mon, 1 Apr 2019 11:53:20 +0800 Subject: [PATCH 04/85] Add timer for mips. --- kernel/Cargo.toml | 2 +- kernel/src/arch/mipsel/consts.rs | 2 +- kernel/src/arch/mipsel/timer.rs | 25 ++++--------------------- 3 files changed, 6 insertions(+), 23 deletions(-) diff --git a/kernel/Cargo.toml b/kernel/Cargo.toml index 1292af8..c1b2642 100644 --- a/kernel/Cargo.toml +++ b/kernel/Cargo.toml @@ -69,7 +69,7 @@ riscv = { git = "https://github.com/rcore-os/riscv", features = ["inline-asm"] } aarch64 = { git = "https://github.com/rcore-os/aarch64" } bcm2837 = { git = "https://github.com/rcore-os/bcm2837", optional = true } -[target.'cfg(target_arch = "mipsel")'.dependencies] +[target.'cfg(target_arch = "mips")'.dependencies] mips = "^0.1.0" [package.metadata.bootimage] diff --git a/kernel/src/arch/mipsel/consts.rs b/kernel/src/arch/mipsel/consts.rs index 3aecac1..a3004b0 100644 --- a/kernel/src/arch/mipsel/consts.rs +++ b/kernel/src/arch/mipsel/consts.rs @@ -39,4 +39,4 @@ pub const USER_STACK_OFFSET: usize = 0x80000000 - USER_STACK_SIZE; pub const USER_STACK_SIZE: usize = 0x10000; pub const USER32_STACK_OFFSET: usize = 0xC0000000 - USER_STACK_SIZE; -pub const MAX_DTB_SIZE: usize = 0x2000; \ No newline at end of file +pub const MAX_DTB_SIZE: usize = 0x2000; diff --git a/kernel/src/arch/mipsel/timer.rs b/kernel/src/arch/mipsel/timer.rs index 8f10c73..466c2d2 100644 --- a/kernel/src/arch/mipsel/timer.rs +++ b/kernel/src/arch/mipsel/timer.rs @@ -1,24 +1,6 @@ -use riscv::register::*; -use super::sbi; +use mips::registers::cp0; use log::*; -#[cfg(target_pointer_width = "64")] -pub fn get_cycle() -> u64 { - time::read() as u64 -} - -#[cfg(target_pointer_width = "32")] -pub fn get_cycle() -> u64 { - loop { - let hi = timeh::read(); - let lo = time::read(); - let tmp = timeh::read(); - if hi == tmp { - return ((hi as u64) << 32) | (lo as u64); - } - } -} - pub fn read_epoch() -> u64 { // TODO: support RTC 0 @@ -27,7 +9,7 @@ pub fn read_epoch() -> u64 { /// Enable timer interrupt pub fn init() { // Enable supervisor timer interrupt - unsafe { sie::set_stimer(); } + cp0::status::enable_hard_int5(); // IP(7), timer interrupt set_next(); info!("timer: init end"); } @@ -36,5 +18,6 @@ pub fn init() { pub fn set_next() { // 100Hz @ QEMU let timebase = 250000; - sbi::set_timer(get_cycle() + timebase); + cp0::count::write_u32(0); + cp0::compare::write_u32(timebase); } From 9bdac887f03358c595e0f89fb2633916d075d2a3 Mon Sep 17 00:00:00 2001 From: Yuhao Zhou Date: Mon, 1 Apr 2019 12:05:22 +0800 Subject: [PATCH 05/85] Remove SBI. --- kernel/src/arch/mipsel/mod.rs | 3 +- kernel/src/arch/mipsel/sbi.rs | 64 ----------------------------------- 2 files changed, 1 insertion(+), 66 deletions(-) delete mode 100644 kernel/src/arch/mipsel/sbi.rs diff --git a/kernel/src/arch/mipsel/mod.rs b/kernel/src/arch/mipsel/mod.rs index 212bdce..d9af59d 100644 --- a/kernel/src/arch/mipsel/mod.rs +++ b/kernel/src/arch/mipsel/mod.rs @@ -1,5 +1,5 @@ pub mod io; -//pub mod interrupt; +pub mod interrupt; pub mod timer; pub mod paging; pub mod memory; @@ -11,7 +11,6 @@ pub mod rand; #[cfg(feature = "board_u540")] #[path = "board/u540/mod.rs"] mod board; -mod sbi; use log::*; diff --git a/kernel/src/arch/mipsel/sbi.rs b/kernel/src/arch/mipsel/sbi.rs deleted file mode 100644 index 0357642..0000000 --- a/kernel/src/arch/mipsel/sbi.rs +++ /dev/null @@ -1,64 +0,0 @@ -//! Port from sbi.h - -#[inline(always)] -fn sbi_call(which: usize, arg0: usize, arg1: usize, arg2: usize) -> usize { - let ret; - unsafe { - asm!("ecall" - : "={x10}" (ret) - : "{x10}" (arg0), "{x11}" (arg1), "{x12}" (arg2), "{x17}" (which) - : "memory" - : "volatile"); - } - ret -} - -pub fn console_putchar(ch: usize) { - sbi_call(SBI_CONSOLE_PUTCHAR, ch, 0, 0); -} - -pub fn console_getchar() -> usize { - sbi_call(SBI_CONSOLE_GETCHAR, 0, 0, 0) -} - -pub fn shutdown() -> ! { - sbi_call(SBI_SHUTDOWN, 0, 0, 0); - unreachable!() -} - -pub fn set_timer(stime_value: u64) { - #[cfg(target_pointer_width = "32")] - sbi_call(SBI_SET_TIMER, stime_value as usize, (stime_value >> 32) as usize, 0); - #[cfg(target_pointer_width = "64")] - sbi_call(SBI_SET_TIMER, stime_value as usize, 0, 0); -} - -pub fn clear_ipi() { - sbi_call(SBI_CLEAR_IPI, 0, 0, 0); -} - -pub fn send_ipi(hart_mask: usize) { - sbi_call(SBI_SEND_IPI, &hart_mask as *const _ as usize, 0, 0); -} - -pub fn remote_fence_i(hart_mask: usize) { - sbi_call(SBI_REMOTE_FENCE_I, &hart_mask as *const _ as usize, 0, 0); -} - -pub fn remote_sfence_vma(hart_mask: usize, _start: usize, _size: usize) { - sbi_call(SBI_REMOTE_SFENCE_VMA, &hart_mask as *const _ as usize, 0, 0); -} - -pub fn remote_sfence_vma_asid(hart_mask: usize, _start: usize, _size: usize, _asid: usize) { - sbi_call(SBI_REMOTE_SFENCE_VMA_ASID, &hart_mask as *const _ as usize, 0, 0); -} - -const SBI_SET_TIMER: usize = 0; -const SBI_CONSOLE_PUTCHAR: usize = 1; -const SBI_CONSOLE_GETCHAR: usize = 2; -const SBI_CLEAR_IPI: usize = 3; -const SBI_SEND_IPI: usize = 4; -const SBI_REMOTE_FENCE_I: usize = 5; -const SBI_REMOTE_SFENCE_VMA: usize = 6; -const SBI_REMOTE_SFENCE_VMA_ASID: usize = 7; -const SBI_SHUTDOWN: usize = 8; From bcff364b1aa05c1c29710dbd875893207978acaf Mon Sep 17 00:00:00 2001 From: Yuhao Zhou Date: Mon, 1 Apr 2019 15:12:17 +0800 Subject: [PATCH 06/85] Add exception handler for MIPS. --- kernel/src/arch/mipsel/boot/regdef.h | 55 ++++++++++ kernel/src/arch/mipsel/boot/trap.S | 150 +++++++++++++++++++++++++++ kernel/src/arch/mipsel/boot/trap.asm | 129 ----------------------- kernel/src/arch/mipsel/context.rs | 34 +++--- kernel/src/arch/mipsel/interrupt.rs | 51 +++++---- 5 files changed, 254 insertions(+), 165 deletions(-) create mode 100644 kernel/src/arch/mipsel/boot/regdef.h create mode 100644 kernel/src/arch/mipsel/boot/trap.S delete mode 100644 kernel/src/arch/mipsel/boot/trap.asm diff --git a/kernel/src/arch/mipsel/boot/regdef.h b/kernel/src/arch/mipsel/boot/regdef.h new file mode 100644 index 0000000..14721cb --- /dev/null +++ b/kernel/src/arch/mipsel/boot/regdef.h @@ -0,0 +1,55 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 1985 MIPS Computer Systems, Inc. + * Copyright (C) 1994, 95, 99, 2003 by Ralf Baechle + * Copyright (C) 1990 - 1992, 1999 Silicon Graphics, Inc. + */ +#ifndef _ASM_REGDEF_H +#define _ASM_REGDEF_H + + + +/* + * Symbolic register names for 32 bit ABI + */ +#define zero $0 /* wired zero */ +#define AT $1 /* assembler temp - uppercase because of ".set at" */ +#define v0 $2 /* return value */ +#define v1 $3 +#define a0 $4 /* argument registers */ +#define a1 $5 +#define a2 $6 +#define a3 $7 +#define t0 $8 /* caller saved */ +#define t1 $9 +#define t2 $10 +#define t3 $11 +#define t4 $12 +#define t5 $13 +#define t6 $14 +#define t7 $15 +#define s0 $16 /* callee saved */ +#define s1 $17 +#define s2 $18 +#define s3 $19 +#define s4 $20 +#define s5 $21 +#define s6 $22 +#define s7 $23 +#define t8 $24 /* caller saved */ +#define t9 $25 +#define jp $25 /* PIC jump register */ +#define k0 $26 /* kernel scratch */ +#define k1 $27 +#define gp $28 /* global pointer */ +#define sp $29 /* stack pointer */ +#define fp $30 /* frame pointer */ +#define s8 $30 /* same like fp! */ +#define ra $31 /* return address */ + + + +#endif /* _ASM_REGDEF_H */ diff --git a/kernel/src/arch/mipsel/boot/trap.S b/kernel/src/arch/mipsel/boot/trap.S new file mode 100644 index 0000000..4da8de4 --- /dev/null +++ b/kernel/src/arch/mipsel/boot/trap.S @@ -0,0 +1,150 @@ +#include "regdef.h" + + .set noat + .set noreorder + .section .text + .globl trap_entry +trap_entry: +# +0x000: TLB-miss vector + b general_trap_vec + +# +0x180: general vector +.org 0x180 +general_trap_vec: + move k1, sp # save stack pointer to k1 + mfc0 k0, $12 # read cp0.status + andi k0, k0, 0x10 # extract cp0.status.ksu + beq k0, zero, trap_from_kernel + nop # delayslot + +trap_from_user: + # TODO: load kstack, we can use k0 to store something + # la k0, address_of_kstack + # addiu sp, k0, size_of_kstack + nop + +trap_from_kernel: + /* + * k0 is damaged + * k1 = old stack pointer + * sp = kernel stack */ + + # allocate 38 words for trapframe + 4 extra words + addiu sp, sp, -168 + + # save general registers + sw ra, 160(sp) + sw fp, 156(sp) + sw k1, 152(sp) # k1 = old sp + sw gp, 148(sp) + sw k1, 144(sp) # real k1 is damaged + sw k0, 140(sp) # real k0 is damaged + sw t9, 136(sp) + sw t8, 132(sp) + sw s7, 128(sp) + sw s6, 124(sp) + sw s5, 120(sp) + sw s4, 116(sp) + sw s3, 112(sp) + sw s2, 108(sp) + sw s1, 104(sp) + sw s0, 100(sp) + sw t7, 96(sp) + sw t6, 92(sp) + sw t5, 88(sp) + sw t4, 84(sp) + sw t3, 80(sp) + sw t2, 76(sp) + sw t1, 72(sp) + sw t0, 68(sp) + sw a3, 64(sp) + sw a2, 60(sp) + sw a1, 56(sp) + sw a0, 52(sp) + sw v1, 48(sp) + sw v0, 44(sp) + sw AT, 40(sp) + nop + + # save hi/lo + mflo t1 + sw t1, 36(sp) + mfhi t0 + sw t0, 32(sp) + + # save special registers + mfc0 t0, $8 # cp0.vaddr + sw t0, 28(sp) + + mfc0 t1, $14 # cp0.epc + sw t1, 24(sp) + + mfc0 t0, $13 # cp0.cause + sw t0, 20(sp) + + mfc0 t1, $12 # cp0.status + sw t1, 16(sp) + + # support nested interrupt + la t0, ~0x1b # reset status.ksu, status.exl, status.ie + and t1, t1, t0 + mtc0 t1, $12 # cp0.status + + # prepare to call rust_trap + jal rust_trap + addiu a0, sp, 16 /* set argument */ + + .globl trap_return +trap_return: + # restore special registers + lw t1, 16(sp) + ori t1, t1, 0x2 # status.exl + nop + mtc0 t1, $12 # cp0.status + + lw k0, 24(sp) + mtc0 k0, $14 # cp0.epc + + lw t0, 32(sp) + mthi t0 + lw t1, 36(sp) + mtlo t1 + + # restore general registers + lw AT, 40(sp) + lw v0, 44(sp) + lw v1, 48(sp) + lw a0, 52(sp) + lw a1, 56(sp) + lw a2, 60(sp) + lw a3, 64(sp) + lw t0, 68(sp) + lw t1, 72(sp) + lw t2, 76(sp) + lw t3, 80(sp) + lw t4, 84(sp) + lw t5, 88(sp) + lw t6, 92(sp) + lw t7, 96(sp) + lw s0, 100(sp) + lw s1, 104(sp) + lw s2, 108(sp) + lw s3, 112(sp) + lw s4, 116(sp) + lw s5, 120(sp) + lw s6, 124(sp) + lw s7, 128(sp) + lw t8, 132(sp) + lw t9, 136(sp) + + # lw k0, 140(sp) + # lw k1, 144(sp) + lw gp, 148(sp) + lw fp, 156(sp) + lw ra, 160(sp) + + lw sp, 152(sp) + + eret + nop + diff --git a/kernel/src/arch/mipsel/boot/trap.asm b/kernel/src/arch/mipsel/boot/trap.asm deleted file mode 100644 index 17ff77e..0000000 --- a/kernel/src/arch/mipsel/boot/trap.asm +++ /dev/null @@ -1,129 +0,0 @@ -# Constants / Macros defined in Rust code: -# XLENB -# LOAD -# STORE -# TEST_BACK_TO_KERNEL - -.macro SAVE_ALL - # If coming from userspace, preserve the user stack pointer and load - # the kernel stack pointer. If we came from the kernel, sscratch - # will contain 0, and we should continue on the current stack. - csrrw sp, sscratch, sp - bnez sp, trap_from_user -trap_from_kernel: - csrr sp, sscratch - STORE gp, -1 - # sscratch = previous-sp, sp = kernel-sp -trap_from_user: - # provide room for trap frame - addi sp, sp, -37 * XLENB - # save x registers except x2 (sp) - STORE x1, 1 - STORE x3, 3 - STORE x4, 4 - STORE x5, 5 - STORE x6, 6 - STORE x7, 7 - STORE x8, 8 - STORE x9, 9 - STORE x10, 10 - STORE x11, 11 - STORE x12, 12 - STORE x13, 13 - STORE x14, 14 - STORE x15, 15 - STORE x16, 16 - STORE x17, 17 - STORE x18, 18 - STORE x19, 19 - STORE x20, 20 - STORE x21, 21 - STORE x22, 22 - STORE x23, 23 - STORE x24, 24 - STORE x25, 25 - STORE x26, 26 - STORE x27, 27 - STORE x28, 28 - STORE x29, 29 - STORE x30, 30 - STORE x31, 31 - - # load hartid to gp from sp[36] - LOAD gp, 36 - - # get sp, sstatus, sepc, stval, scause - # set sscratch = 0 - csrrw s0, sscratch, x0 - csrr s1, sstatus - csrr s2, sepc - csrr s3, stval - csrr s4, scause - # store sp, sstatus, sepc, sbadvaddr, scause - STORE s0, 2 - STORE s1, 32 - STORE s2, 33 - STORE s3, 34 - STORE s4, 35 -.endm - -.macro RESTORE_ALL - LOAD s1, 32 # s1 = sstatus - LOAD s2, 33 # s2 = sepc - andi s0, s1, 1 << 8 # sstatus.SPP = 1 - bnez s0, _to_kernel # s0 = back to kernel? -_to_user: - addi s0, sp, 37*XLENB - csrw sscratch, s0 # sscratch = kernel-sp - STORE gp, 36 # store hartid from gp to sp[36] -_to_kernel: - # restore sstatus, sepc - csrw sstatus, s1 - csrw sepc, s2 - - # restore x registers except x2 (sp) - LOAD x1, 1 - LOAD x3, 3 - LOAD x4, 4 - LOAD x5, 5 - LOAD x6, 6 - LOAD x7, 7 - LOAD x8, 8 - LOAD x9, 9 - LOAD x10, 10 - LOAD x11, 11 - LOAD x12, 12 - LOAD x13, 13 - LOAD x14, 14 - LOAD x15, 15 - LOAD x16, 16 - LOAD x17, 17 - LOAD x18, 18 - LOAD x19, 19 - LOAD x20, 20 - LOAD x21, 21 - LOAD x22, 22 - LOAD x23, 23 - LOAD x24, 24 - LOAD x25, 25 - LOAD x26, 26 - LOAD x27, 27 - LOAD x28, 28 - LOAD x29, 29 - LOAD x30, 30 - LOAD x31, 31 - # restore sp last - LOAD x2, 2 -.endm - - .section .text - .globl trap_entry -trap_entry: - SAVE_ALL - mv a0, sp - jal rust_trap - .globl trap_return -trap_return: - RESTORE_ALL - # return from supervisor call - sret diff --git a/kernel/src/arch/mipsel/context.rs b/kernel/src/arch/mipsel/context.rs index a8b6e5f..dc6eea7 100644 --- a/kernel/src/arch/mipsel/context.rs +++ b/kernel/src/arch/mipsel/context.rs @@ -1,23 +1,27 @@ -use riscv::register::{ - sstatus, - sstatus::Sstatus, - scause::Scause, -}; +use mips::registers; /// Saved registers on a trap. #[derive(Clone)] #[repr(C)] pub struct TrapFrame { - /// General registers - pub x: [usize; 32], - /// Supervisor Status - pub sstatus: Sstatus, - /// Supervisor Exception Program Counter - pub sepc: usize, - /// Supervisor Trap Value - pub stval: usize, - /// Supervisor Cause - pub scause: Scause, + /// CP0 status register + pub status: usize; + /// CP0 cause register + pub cause: usize; + /// CP0 EPC register + pub epc: usize; + /// CP0 vaddr register + pub vaddr: usize; + /// HI/LO registers + pub hi, lo: usize; + /// General registers 1-7 + pub at, v0, v1, a0, a1, a2, a3: u32; + /// General registers 8-15 + pub t0, t1, t2, t3, t4, t5, t6, t7: u32; + /// General registers 16-23 + pub s0, s1, s2, s3, s4, s5, s6, s7: u32; + /// General registers 24-31 + pub t8, t9, k0, k1, gp, sp, fp, ra: u32; /// Reserve space for hartid pub _hartid: usize, } diff --git a/kernel/src/arch/mipsel/interrupt.rs b/kernel/src/arch/mipsel/interrupt.rs index 9488234..f6bea8a 100644 --- a/kernel/src/arch/mipsel/interrupt.rs +++ b/kernel/src/arch/mipsel/interrupt.rs @@ -1,4 +1,5 @@ use mips::interrupts::*; +use mips::registers::*; use crate::drivers::DRIVERS; pub use self::context::*; use log::*; @@ -8,6 +9,7 @@ mod context; /// Initialize interrupt pub fn init() { + // TODO // extern { // fn trap_entry(); // } @@ -30,23 +32,23 @@ pub fn init() { /// Enable interrupt #[inline] pub unsafe fn enable() { - // sstatus::set_sie(); + interrupts::enable(); } /// Disable interrupt and return current interrupt status #[inline] pub unsafe fn disable_and_store() -> usize { - // let e = sstatus::read().sie() as usize; - // sstatus::clear_sie(); - // e + let e = cp0::status::read_u32() & 1; + interrupts::disable(); + e } /// Enable interrupt if `flags` != 0 #[inline] pub unsafe fn restore(flags: usize) { - // if flags != 0 { - // enable(); - // } + if flags != 0 { + enable(); + } } /// Dispatch and handle interrupt. @@ -54,22 +56,24 @@ pub unsafe fn restore(flags: usize) { /// This function is called from `trap.asm`. #[no_mangle] pub extern fn rust_trap(tf: &mut TrapFrame) { - // use self::scause::{Trap, Interrupt as I, Exception as E}; - // trace!("Interrupt @ CPU{}: {:?} ", super::cpu::id(), tf.scause.cause()); - // match tf.scause.cause() { - // Trap::Interrupt(I::SupervisorExternal) => external(), - // Trap::Interrupt(I::SupervisorSoft) => ipi(), - // Trap::Interrupt(I::SupervisorTimer) => timer(), - // Trap::Exception(E::UserEnvCall) => syscall(tf), - // Trap::Exception(E::LoadPageFault) => page_fault(tf), - // Trap::Exception(E::StorePageFault) => page_fault(tf), - // Trap::Exception(E::InstructionPageFault) => page_fault(tf), - // _ => crate::trap::error(tf), - // } - // trace!("Interrupt end"); + // TODO + use self::scause::{Trap, Interrupt as I, Exception as E}; + // trace!("Interrupt @ CPU{}: {:?} ", super::cpu::id(), tf.scause.cause()); + match tf.scause.cause() { + Trap::Interrupt(I::SupervisorExternal) => external(), + Trap::Interrupt(I::SupervisorSoft) => ipi(), + Trap::Interrupt(I::SupervisorTimer) => timer(), + Trap::Exception(E::UserEnvCall) => syscall(tf), + Trap::Exception(E::LoadPageFault) => page_fault(tf), + Trap::Exception(E::StorePageFault) => page_fault(tf), + Trap::Exception(E::InstructionPageFault) => page_fault(tf), + _ => crate::trap::error(tf), + } + trace!("Interrupt end"); } fn external() { + // TODO #[cfg(feature = "board_u540")] unsafe { super::board::handle_external_interrupt(); } @@ -83,6 +87,7 @@ fn external() { } fn try_process_serial() -> bool { + // TODO match super::io::getchar_option() { Some(ch) => { crate::trap::serial(ch); @@ -93,6 +98,7 @@ fn try_process_serial() -> bool { } fn try_process_drivers() -> bool { + // TODO for driver in DRIVERS.read().iter() { if driver.try_handle_interrupt(None) == true { return true @@ -102,8 +108,9 @@ fn try_process_drivers() -> bool { } fn ipi() { + // TODO debug!("IPI"); - super::sbi::clear_ipi(); +// super::sbi::clear_ipi(); } fn timer() { @@ -112,12 +119,14 @@ fn timer() { } fn syscall(tf: &mut TrapFrame) { + // TODO tf.sepc += 4; // Must before syscall, because of fork. let ret = crate::syscall::syscall(tf.x[17], [tf.x[10], tf.x[11], tf.x[12], tf.x[13], tf.x[14], tf.x[15]], tf); tf.x[10] = ret as usize; } fn page_fault(tf: &mut TrapFrame) { + // TODO let addr = tf.stval; trace!("\nEXCEPTION: Page Fault @ {:#x}", addr); From 52758e6620fec4d515e87f3fa2fe24eae989ea2f Mon Sep 17 00:00:00 2001 From: Harry Chen Date: Mon, 1 Apr 2019 18:26:55 +0800 Subject: [PATCH 07/85] Add simple bootloader for mipsel Signed-off-by: Harry Chen --- bootloader/Makefile | 3 ++ bootloader/build.rs | 24 +++++++++++++++- bootloader/src/arch/mipsel/boot.S | 20 +++++++++++++ bootloader/src/arch/mipsel/boot.ld | 41 ++++++++++++++++++++++++++ bootloader/src/arch/mipsel/mod.rs | 34 ++++++++++++++++++++++ bootloader/src/main.rs | 46 ++++++++++++++++++++++++++++-- bootloader/targets/mipsel.json | 36 +++++++++++++++++++++++ 7 files changed, 201 insertions(+), 3 deletions(-) create mode 100644 bootloader/src/arch/mipsel/boot.S create mode 100644 bootloader/src/arch/mipsel/boot.ld create mode 100644 bootloader/src/arch/mipsel/mod.rs create mode 100644 bootloader/targets/mipsel.json diff --git a/bootloader/Makefile b/bootloader/Makefile index e675023..2e51b7d 100644 --- a/bootloader/Makefile +++ b/bootloader/Makefile @@ -13,6 +13,8 @@ else ifeq ($(arch), riscv32) prefix := riscv64-unknown-elf- else ifeq ($(arch), riscv64) prefix := riscv64-unknown-elf- +else ifeq ($(arch), mipsel) +prefix := mipsel-linux-gnu- else ifeq ($(arch), aarch64) prefix ?= aarch64-none-elf- ifeq (,$(shell which $(prefix)ld)) @@ -30,6 +32,7 @@ strip := $(prefix)strip export CC = $(cc) export PAYLOAD = $(payload) +export DTB = $(dtb) build_args := --target=targets/$(arch).json ifeq ($(mode), release) diff --git a/bootloader/build.rs b/bootloader/build.rs index 958e977..3a91fca 100644 --- a/bootloader/build.rs +++ b/bootloader/build.rs @@ -10,14 +10,22 @@ fn main() { } } +/// include payload and dtb in sections of asm fn gen_payload_asm() -> Result { let out_dir = std::env::var("OUT_DIR").unwrap(); let payload = std::env::var("PAYLOAD").unwrap(); + let dtb = std::env::var("DTB").unwrap(); if !Path::new(&payload).is_file() { panic!("Kernel payload `{}` not found", payload) } + let mut has_dtb = true; + + if !Path::new(&dtb).is_file() { + has_dtb = false; + } + let file_path = Path::new(&out_dir).join("payload.S"); let mut f = File::create(&file_path).unwrap(); @@ -31,10 +39,24 @@ fn gen_payload_asm() -> Result { _kernel_payload_start: .incbin "{}" _kernel_payload_end: -"#, payload)?; + "#, payload)?; println!("cargo:rerun-if-changed={}", payload); println!("cargo:rerun-if-env-changed=PAYLOAD"); + if has_dtb { + write!(f, r#" + .section .dtb,"a" + .align 12 + .global _dtb_start, _dtb_end +_dtb_start: + .incbin "{}" +_dtb_end: + "#, dtb)?; + println!("{:x?} {:x?}", dtb, file_path); + println!("cargo:rerun-if-changed={}", dtb); + println!("cargo:rerun-if-env-changed=DTB"); + } + Ok(file_path) } diff --git a/bootloader/src/arch/mipsel/boot.S b/bootloader/src/arch/mipsel/boot.S new file mode 100644 index 0000000..ffcf6da --- /dev/null +++ b/bootloader/src/arch/mipsel/boot.S @@ -0,0 +1,20 @@ +.section .text.boot +.globl _start + +_start: + # read cpu affinity, start core 0, halt the rest + mfc0 $8, $15, 1 + beqz $8, setup + andi $8, $8, 0x3ff # use bits 11 ~ 0 + +halt: + # core affinity != 0, halt it + b halt + nop + +setup: + # put the bootstack at 8MB offset of physical mem + la $29, 0x80800000 # $sp + la $28, _gp # $gp + b boot_main + nop \ No newline at end of file diff --git a/bootloader/src/arch/mipsel/boot.ld b/bootloader/src/arch/mipsel/boot.ld new file mode 100644 index 0000000..f62b631 --- /dev/null +++ b/bootloader/src/arch/mipsel/boot.ld @@ -0,0 +1,41 @@ +ENTRY(_start) + +SECTIONS { + + /* MIPS entry point after cold reset */ + . = 0xBFC00000; + + .text : { + KEEP(*(.text.boot)) /* from boot.S */ + *(.text .text.* .gnu.linkonce.t*) + . = ALIGN(4K); + } + + .rodata : { + *(.rodata .rodata.* .gnu.linkonce.r*) + . = ALIGN(4K); + } + + .data : { + *(.data .data.* .gnu.linkonce.d*) + . = ALIGN(4K); + } + + .bss : { + _sbss = .; + *(.bss .bss.*) + *(COMMON) + . = ALIGN(4K); + _ebss = .; + } + + .payload : { + *(.payload) + } + + .dtb : { + *(.dtb) + } + + /DISCARD/ : { *(.comment) *(.gnu*) *(.note*) *(.eh_frame*) } +} diff --git a/bootloader/src/arch/mipsel/mod.rs b/bootloader/src/arch/mipsel/mod.rs new file mode 100644 index 0000000..14237b6 --- /dev/null +++ b/bootloader/src/arch/mipsel/mod.rs @@ -0,0 +1,34 @@ +use core::ptr; +use fixedvec::FixedVec; +use xmas_elf::program::{ProgramHeader32, Type}; + +const KERNEL_OFFSET: u32 = 0x80000000; + +global_asm!(include_str!("boot.S")); + +pub fn copy_kernel(kernel_start: usize, segments: &FixedVec) { + // reverse program headers to avoid overlapping in memory copying + let mut space = alloc_stack!([ProgramHeader32; 32]); + let mut rev_segments = FixedVec::new(&mut space); + for i in (0..segments.len()).rev() { + rev_segments.push(segments[i]).unwrap(); + } + + for segment in &rev_segments { + if segment.get_type() != Ok(Type::Load) { + continue; + } + let virt_addr = segment.virtual_addr; + let offset = segment.offset; + let file_size = segment.file_size; + let mem_size = segment.mem_size; + + unsafe { + let src = (kernel_start as u32 + offset) as *const u8; + let dst = virt_addr.wrapping_sub(KERNEL_OFFSET) as *mut u8; + ptr::copy(src, dst, file_size as usize); + ptr::write_bytes(dst.offset(file_size as isize), 0, (mem_size - file_size) as usize); + } + } + +} diff --git a/bootloader/src/main.rs b/bootloader/src/main.rs index 88a6ac7..c886029 100644 --- a/bootloader/src/main.rs +++ b/bootloader/src/main.rs @@ -12,13 +12,18 @@ use core::slice; use fixedvec::FixedVec; use xmas_elf::{ header, - program::{ProgramHeader, ProgramHeader64}, + program::{ProgramHeader, ProgramHeader32, ProgramHeader64}, ElfFile, }; #[cfg(target_arch = "aarch64")] #[path = "arch/aarch64/mod.rs"] pub mod arch; + +#[cfg(target_arch = "mips")] +#[path = "arch/mipsel/mod.rs"] +pub mod arch; + pub mod lang_items; extern "C" { @@ -26,8 +31,15 @@ extern "C" { fn _kernel_payload_end(); } +#[cfg(target_arch = "mips")] +extern "C" { + fn _dtb_start(); + fn _dtb_end(); +} + /// The entry point of bootloader -#[no_mangle] // don't mangle the name of this function +#[cfg(target_arch = "aarch64")] +#[no_mangle] pub extern "C" fn boot_main() -> ! { let kernel_size = _kernel_payload_end as usize - _kernel_payload_start as usize; let kernel = unsafe { slice::from_raw_parts(_kernel_payload_start as *const u8, kernel_size) }; @@ -54,3 +66,33 @@ pub extern "C" fn boot_main() -> ! { loop {} } + + +#[cfg(target_arch = "mips")] +#[no_mangle] +pub extern "C" fn boot_main() -> ! { + let kernel_size = _kernel_payload_end as usize - _kernel_payload_start as usize; + let kernel = unsafe { slice::from_raw_parts(_kernel_payload_start as *const u8, kernel_size) }; + let kernel_elf = ElfFile::new(kernel).unwrap(); + header::sanity_check(&kernel_elf).unwrap(); + + let mut preallocated_space = alloc_stack!([ProgramHeader32; 32]); + let mut segments = FixedVec::new(&mut preallocated_space); + + for program_header in kernel_elf.program_iter() { + match program_header { + ProgramHeader::Ph32(header) => segments + .push(*header) + .expect("does not support more than 32 program segments"), + ProgramHeader::Ph64(_) => panic!("does not support 64 bit elf files"), + } + } + + let entry = kernel_elf.header.pt2.entry_point() as u32; + let kernel_main: extern "C" fn(dtb: usize) = unsafe { transmute(entry) }; + + arch::copy_kernel(_kernel_payload_start as usize, &segments); + kernel_main(_dtb_start as usize); + + loop {} +} diff --git a/bootloader/targets/mipsel.json b/bootloader/targets/mipsel.json new file mode 100644 index 0000000..d343fe4 --- /dev/null +++ b/bootloader/targets/mipsel.json @@ -0,0 +1,36 @@ +{ + "arch": "mips", + "cpu": "mips32r2", + "llvm-target": "mipsel-unknown-none", + "data-layout": "e-m:m-p:32:32-i8:8:32-i16:16:32-i64:64-n32-S64", + "target-endian": "little", + "target-pointer-width": "32", + "target-c-int-width": "32", + "os": "none", + "features": "+mips32r2", + "max-atomic-width": "32", + "linker": "rust-lld", + "linker-flavor": "ld.lld", + "pre-link-args": { + "ld.lld": [ + "-Tsrc/arch/mipsel/boot.ld" + ] + }, + "executables": true, + "panic-strategy": "abort", + "relocation-model": "static", + "abi-blacklist": [ + "cdecl", + "stdcall", + "fastcall", + "vectorcall", + "thiscall", + "aapcs", + "win64", + "sysv64", + "ptx-kernel", + "msp430-interrupt", + "x86-interrupt" + ], + "eliminate-frame-pointer": false +} From d588a922abdd50523378ca9c90be08962b47d710 Mon Sep 17 00:00:00 2001 From: Yuhao Zhou Date: Mon, 1 Apr 2019 22:36:12 +0800 Subject: [PATCH 08/85] Fix some syntax errors. --- .../arch/mipsel/boot/{entry.asm => entry.S} | 13 +++-- kernel/src/arch/mipsel/context.rs | 51 ++++++++++++++----- kernel/src/arch/mipsel/mod.rs | 4 +- 3 files changed, 46 insertions(+), 22 deletions(-) rename kernel/src/arch/mipsel/boot/{entry.asm => entry.S} (58%) diff --git a/kernel/src/arch/mipsel/boot/entry.asm b/kernel/src/arch/mipsel/boot/entry.S similarity index 58% rename from kernel/src/arch/mipsel/boot/entry.asm rename to kernel/src/arch/mipsel/boot/entry.S index 3cee2fd..80ecb42 100644 --- a/kernel/src/arch/mipsel/boot/entry.asm +++ b/kernel/src/arch/mipsel/boot/entry.S @@ -1,14 +1,13 @@ +#include "regdef.h" + + .set noreorder .section .text.entry .globl _start _start: - add t0, a0, 1 - slli t0, t0, 16 - - lui sp, %hi(bootstack) - addi sp, sp, %lo(bootstack) - add sp, sp, t0 + la sp, bootstacktop - call rust_main + b rust_main + nop .section .bss.stack .align 12 #PGSHIFT diff --git a/kernel/src/arch/mipsel/context.rs b/kernel/src/arch/mipsel/context.rs index dc6eea7..8c4a996 100644 --- a/kernel/src/arch/mipsel/context.rs +++ b/kernel/src/arch/mipsel/context.rs @@ -5,23 +5,48 @@ use mips::registers; #[repr(C)] pub struct TrapFrame { /// CP0 status register - pub status: usize; + pub status: u32, /// CP0 cause register - pub cause: usize; + pub cause: u32, /// CP0 EPC register - pub epc: usize; + pub epc: u32, /// CP0 vaddr register - pub vaddr: usize; + pub vaddr: u32, /// HI/LO registers - pub hi, lo: usize; - /// General registers 1-7 - pub at, v0, v1, a0, a1, a2, a3: u32; - /// General registers 8-15 - pub t0, t1, t2, t3, t4, t5, t6, t7: u32; - /// General registers 16-23 - pub s0, s1, s2, s3, s4, s5, s6, s7: u32; - /// General registers 24-31 - pub t8, t9, k0, k1, gp, sp, fp, ra: u32; + pub hi: u32, + pub lo: u32, + /// General registers + pub at: u32, + pub v0: u32, + pub v1: u32, + pub a0: u32, + pub a1: u32, + pub a2: u32, + pub a3: u32, + pub t0: u32, + pub t1: u32, + pub t2: u32, + pub t3: u32, + pub t4: u32, + pub t5: u32, + pub t6: u32, + pub t7: u32, + pub s0: u32, + pub s1: u32, + pub s2: u32, + pub s3: u32, + pub s4: u32, + pub s5: u32, + pub s6: u32, + pub s7: u32, + pub t8: u32, + pub t9: u32, + pub k0: u32, + pub k1: u32, + pub gp: u32, + pub sp: u32, + pub fp: u32, + pub ra: u32, /// Reserve space for hartid pub _hartid: usize, } diff --git a/kernel/src/arch/mipsel/mod.rs b/kernel/src/arch/mipsel/mod.rs index d9af59d..02bb307 100644 --- a/kernel/src/arch/mipsel/mod.rs +++ b/kernel/src/arch/mipsel/mod.rs @@ -83,5 +83,5 @@ global_asm!(r" "); -global_asm!(include_str!("boot/entry.asm")); -global_asm!(include_str!("boot/trap.asm")); +global_asm!(include_str!("boot/entry.S")); +global_asm!(include_str!("boot/trap.S")); From 34c3d139a138eb42b29167bc19ab24180dd8a7df Mon Sep 17 00:00:00 2001 From: Harry Chen Date: Mon, 1 Apr 2019 23:07:49 +0800 Subject: [PATCH 09/85] Modify linker script to mipsel arch, add dts in kernel binary Signed-off-by: Harry Chen --- kernel/Makefile | 37 +++++++++-- kernel/build.rs | 30 +++++++++ kernel/src/arch/mipsel/board/u540/linker.ld | 49 -------------- kernel/src/arch/mipsel/board/u540/mod.rs | 18 ----- kernel/src/arch/mipsel/boot/dts/malta.dts | 0 kernel/src/arch/mipsel/boot/entry.S | 2 + kernel/src/arch/mipsel/boot/linker.ld | 10 +-- kernel/src/arch/mipsel/boot/linker64.ld | 49 -------------- kernel/src/arch/mipsel/consts.rs | 24 ------- kernel/src/arch/mipsel/mod.rs | 74 ++++++++------------- 10 files changed, 92 insertions(+), 201 deletions(-) delete mode 100644 kernel/src/arch/mipsel/board/u540/linker.ld delete mode 100644 kernel/src/arch/mipsel/board/u540/mod.rs create mode 100644 kernel/src/arch/mipsel/boot/dts/malta.dts delete mode 100644 kernel/src/arch/mipsel/boot/linker64.ld diff --git a/kernel/Makefile b/kernel/Makefile index 3a077d7..9ba6c2c 100644 --- a/kernel/Makefile +++ b/kernel/Makefile @@ -42,18 +42,24 @@ build_path := target/$(target)/$(mode) kernel := $(build_path)/rcore kernel_img := $(build_path)/kernel.img bootimage := $(build_path)/bootimage.bin +dtb := src/arch/$(arch)/boot/dts/$(board).dtb bootloader_dir = ../bootloader bootloader := $(bootloader_dir)/target/$(target)/$(mode)/rcore-bootloader bbl_path := $(PWD)/../riscv-pk user_dir := ../user +ifeq ($(arch), aarch64) +board := raspi3 + +ifeq ($(arch), mipsel) +board := malta + ### export environments ### export ARCH = $(arch) export BOARD = $(board) export SMP = $(smp) +export DTB = $(dtb) export SFSIMG = $(user_dir)/build/$(arch).qcow2 -ifeq ($(arch), aarch64) -board := raspi3 export SFSIMG = $(user_dir)/build/$(arch).img endif @@ -104,6 +110,13 @@ qemu_opts += \ -kernel $(kernel_img) endif +else ifeq ($(arch), mipsel) +qemu_opts += \ + -machine $(board) \ + -serial null -serial mon:stdio \ + -kernel $(kernel_img) +endif + ifdef d qemu_opts += -d $(d) endif @@ -171,9 +184,10 @@ cc := $(prefix)gcc as := $(prefix)as gdb := $(prefix)gdb strip := $(prefix)strip +dtc := dtc export CC = $(cc) -.PHONY: all clean build asm doc debug kernel sfsimg install run justrun runnet justrunnet runui justrunui runtest justruntest +.PHONY: all clean build asm doc debug kernel sfsimg install run justrun runnet justrunnet runui justrunui runtest justruntest all: kernel @@ -220,8 +234,18 @@ header: sym: @$(objdump) -t $(kernel) | less +### device tree process ### + +%.dtb: %.dts + $(dtc) -I dts -O dtb -o $@ $< + +### bootloader and kernel image ### + $(bootloader): $(kernel) ifeq ($(arch), aarch64) + need_bootloader := true +endif +ifeq ($(need_bootloader), true) @echo Building $(arch) bootloader @$(strip) $(kernel) -o $(kernel)_stripped @cd $(bootloader_dir) && make arch=$(arch) mode=$(mode) payload=../kernel/$(kernel)_stripped @@ -254,11 +278,12 @@ else ifeq ($(arch), riscv64) else ifeq ($(arch), aarch64) @$(objcopy) $(bootloader) --strip-all -O binary $@ else ifeq ($(arch), mipsel) - # TODO write mipsel bootloader - false + # qemu-system-mipsel accepts ELF file only, so don't use objcopy + @cp $(kernel) $(kernel)_orig + @$(strip) $(kernel) -o $(kernel) endif -kernel: +kernel: $(dtb) @echo Building $(arch) kernel ifeq ($(arch), x86_64) @bootimage build $(build_args) diff --git a/kernel/build.rs b/kernel/build.rs index 657f765..9602b9b 100644 --- a/kernel/build.rs +++ b/kernel/build.rs @@ -19,6 +19,7 @@ fn main() { "riscv64" => { } "mipsel" => { + gen_dtb_asm().unwrap(); } "aarch64" => { } @@ -49,3 +50,32 @@ fn gen_vector_asm() -> Result<()> { } Ok(()) } + + +fn gen_dtb_asm() -> Result<()> { + let arch = std::env::var("ARCH").unwrap(); + let dtb = std::env::var("DTB").unwrap(); + let board = std::env::var("BOARD").unwrap(); + + if !Path::new(&dtb).is_file() { + panic!("DTB `{}` not found", dtb) + } + + let mut f = File::create(format!("src/arch/{}/boot/dtb.S", arch)).unwrap(); + + println!("cargo:rerun-if-changed={}", dtb); + println!("cargo:rerun-if-env-changed=DTB"); + + writeln!(f, "# generated by build.rs - do not edit")?; + writeln!(f, ".intel_syntax noprefix")?; + write!(f, r#" + .section .dtb,"a" + .align 12 + .global _dtb_start, _dtb_end +_dtb_start: + .incbin "{}" +_dtb_end: + "#, dtb)?; + + Ok(()) +} \ No newline at end of file diff --git a/kernel/src/arch/mipsel/board/u540/linker.ld b/kernel/src/arch/mipsel/board/u540/linker.ld deleted file mode 100644 index 6bbe85b..0000000 --- a/kernel/src/arch/mipsel/board/u540/linker.ld +++ /dev/null @@ -1,49 +0,0 @@ -/* Copy from bbl-ucore : https://ring00.github.io/bbl-ucore */ - -/* Simple linker script for the ucore kernel. - See the GNU ld 'info' manual ("info ld") to learn the syntax. */ - -OUTPUT_ARCH(riscv) -ENTRY(_start) - -BASE_ADDRESS = 0xffffffffc0020000; - -SECTIONS -{ - /* Load the kernel at this address: "." means the current address */ - . = BASE_ADDRESS; - start = .; - - .text : { - stext = .; - *(.text.entry) - *(.text .text.*) - . = ALIGN(4K); - etext = .; - } - - .rodata : { - srodata = .; - *(.rodata .rodata.*) - . = ALIGN(4K); - erodata = .; - } - - .data : { - sdata = .; - *(.data .data.*) - edata = .; - } - - .stack : { - *(.bss.stack) - } - - .bss : { - sbss = .; - *(.bss .bss.*) - ebss = .; - } - - PROVIDE(end = .); -} diff --git a/kernel/src/arch/mipsel/board/u540/mod.rs b/kernel/src/arch/mipsel/board/u540/mod.rs deleted file mode 100644 index cc53874..0000000 --- a/kernel/src/arch/mipsel/board/u540/mod.rs +++ /dev/null @@ -1,18 +0,0 @@ -use super::consts::KERNEL_OFFSET; - -/// Mask all external interrupt except serial. -pub unsafe fn init_external_interrupt() { - const HART1_S_MODE_INTERRUPT_ENABLES: *mut u64 = (KERNEL_OFFSET + 0x0C00_2100) as *mut u64; - const SERIAL: u64 = 4; - HART1_S_MODE_INTERRUPT_ENABLES.write(1 << SERIAL); -} - -/// Claim and complete external interrupt by reading and writing to -/// PLIC Interrupt Claim/Complete Register. -pub unsafe fn handle_external_interrupt() { - const HART1_S_MODE_INTERRUPT_CLAIM_COMPLETE: *mut u32 = (KERNEL_OFFSET + 0x0C20_2004) as *mut u32; - // claim - let source = HART1_S_MODE_INTERRUPT_CLAIM_COMPLETE.read(); - // complete - HART1_S_MODE_INTERRUPT_CLAIM_COMPLETE.write(source); -} \ No newline at end of file diff --git a/kernel/src/arch/mipsel/boot/dts/malta.dts b/kernel/src/arch/mipsel/boot/dts/malta.dts new file mode 100644 index 0000000..e69de29 diff --git a/kernel/src/arch/mipsel/boot/entry.S b/kernel/src/arch/mipsel/boot/entry.S index 80ecb42..5d2ad14 100644 --- a/kernel/src/arch/mipsel/boot/entry.S +++ b/kernel/src/arch/mipsel/boot/entry.S @@ -3,8 +3,10 @@ .set noreorder .section .text.entry .globl _start + _start: la sp, bootstacktop + la gp, _gp b rust_main nop diff --git a/kernel/src/arch/mipsel/boot/linker.ld b/kernel/src/arch/mipsel/boot/linker.ld index bc3ba7f..8d09ddb 100644 --- a/kernel/src/arch/mipsel/boot/linker.ld +++ b/kernel/src/arch/mipsel/boot/linker.ld @@ -1,21 +1,14 @@ -/* Copy from bbl-ucore : https://ring00.github.io/bbl-ucore */ - /* Simple linker script for the ucore kernel. See the GNU ld 'info' manual ("info ld") to learn the syntax. */ OUTPUT_ARCH(riscv) ENTRY(_start) -BASE_ADDRESS = 0xC0020000; +BASE_ADDRESS = 0x80100000; SECTIONS { - . = 0xC0000000; - .boot : { - KEEP(*(.text.boot)) - } - /* Load the kernel at this address: "." means the current address */ . = BASE_ADDRESS; start = .; @@ -30,6 +23,7 @@ SECTIONS .rodata : { srodata = .; *(.rodata .rodata.*) + *(.dtb) . = ALIGN(4K); erodata = .; } diff --git a/kernel/src/arch/mipsel/boot/linker64.ld b/kernel/src/arch/mipsel/boot/linker64.ld deleted file mode 100644 index 6bbe85b..0000000 --- a/kernel/src/arch/mipsel/boot/linker64.ld +++ /dev/null @@ -1,49 +0,0 @@ -/* Copy from bbl-ucore : https://ring00.github.io/bbl-ucore */ - -/* Simple linker script for the ucore kernel. - See the GNU ld 'info' manual ("info ld") to learn the syntax. */ - -OUTPUT_ARCH(riscv) -ENTRY(_start) - -BASE_ADDRESS = 0xffffffffc0020000; - -SECTIONS -{ - /* Load the kernel at this address: "." means the current address */ - . = BASE_ADDRESS; - start = .; - - .text : { - stext = .; - *(.text.entry) - *(.text .text.*) - . = ALIGN(4K); - etext = .; - } - - .rodata : { - srodata = .; - *(.rodata .rodata.*) - . = ALIGN(4K); - erodata = .; - } - - .data : { - sdata = .; - *(.data .data.*) - edata = .; - } - - .stack : { - *(.bss.stack) - } - - .bss : { - sbss = .; - *(.bss .bss.*) - ebss = .; - } - - PROVIDE(end = .); -} diff --git a/kernel/src/arch/mipsel/consts.rs b/kernel/src/arch/mipsel/consts.rs index a3004b0..15d4f8e 100644 --- a/kernel/src/arch/mipsel/consts.rs +++ b/kernel/src/arch/mipsel/consts.rs @@ -1,40 +1,16 @@ // Physical address available on THINPAD: // [0x80000000, 0x80800000] -#[cfg(target_arch = "riscv32")] -pub const RECURSIVE_INDEX: usize = 0x3fd; -#[cfg(target_arch = "riscv64")] -pub const RECURSIVE_INDEX: usize = 0o774; -// Under riscv64, upon booting, paging is enabled by bbl and -// root_table[0777] maps to p3_table, -// and p3_table[0777] maps to gigapage 8000_0000H, -// so 0xFFFF_FFFF_8000_0000 maps to 0x8000_0000 -// root_table[0774] points to root_table itself as page table -// root_table[0775] points to root_table itself as leaf page -// root_table[0776] points to a temp page table as leaf page -#[cfg(target_arch = "riscv32")] pub const KERNEL_OFFSET: usize = 0xC000_0000; -#[cfg(target_arch = "riscv64")] -pub const KERNEL_OFFSET: usize = 0xFFFF_FFFF_C000_0000; #[cfg(target_arch = "riscv32")] pub const KERNEL_P2_INDEX: usize = (KERNEL_OFFSET >> 12 >> 10) & 0x3ff; -#[cfg(target_arch = "riscv64")] -pub const KERNEL_P4_INDEX: usize = (KERNEL_OFFSET >> 12 >> 9 >> 9 >> 9) & 0o777; pub const KERNEL_HEAP_SIZE: usize = 0x00a0_0000; -#[cfg(target_arch = "riscv32")] -pub const MEMORY_OFFSET: usize = 0x8000_0000; -#[cfg(target_arch = "riscv64")] pub const MEMORY_OFFSET: usize = 0x8000_0000; - -#[cfg(target_arch = "riscv32")] -pub const MEMORY_END: usize = 0x8100_0000; -#[cfg(target_arch = "riscv64")] pub const MEMORY_END: usize = 0x8100_0000; -// FIXME: rv64 `sh` and `ls` will crash if stack top > 0x80000000 ??? pub const USER_STACK_OFFSET: usize = 0x80000000 - USER_STACK_SIZE; pub const USER_STACK_SIZE: usize = 0x10000; pub const USER32_STACK_OFFSET: usize = 0xC0000000 - USER_STACK_SIZE; diff --git a/kernel/src/arch/mipsel/mod.rs b/kernel/src/arch/mipsel/mod.rs index 02bb307..a84a54d 100644 --- a/kernel/src/arch/mipsel/mod.rs +++ b/kernel/src/arch/mipsel/mod.rs @@ -8,41 +8,48 @@ pub mod consts; pub mod cpu; pub mod syscall; pub mod rand; -#[cfg(feature = "board_u540")] -#[path = "board/u540/mod.rs"] -mod board; use log::*; +use mips::registers; +use mips::instructions; + +extern "C" { + fn _dtb_start(); + fn _dtb_end(); +} #[no_mangle] -pub extern fn rust_main(hartid: usize, dtb: usize, hart_mask: usize) -> ! { - // An initial recursive page table has been set by BBL (shared by all cores) +pub extern fn rust_main() -> ! { + + // unsafe { cpu::set_cpu_id(hartid); } - unsafe { cpu::set_cpu_id(hartid); } + let ebase = cp0::ebase::read_u32(); + let cpu_id = ebase & 0x3ff; + let dtb_start = _dtb_start as usize; + let dtb_end = _dtb_end as usize; - if hartid != BOOT_HART_ID { - while unsafe { !cpu::has_started(hartid) } { } - println!("Hello RISCV! in hart {}, dtb @ {:#x}", hartid, dtb); - others_main(); - //other_main -> ! + if cpu_id != BOOT_CPU_ID { + // TODO: run others_main on other CPU + // while unsafe { !cpu::has_started(hartid) } { } + // println!("Hello RISCV! in hart {}, dtb @ {:#x}", hartid, dtb); + // others_main(); + loop {} } unsafe { memory::clear_bss(); } - println!("Hello RISCV! in hart {}, dtb @ {:#x}", hartid, dtb); + println!("Hello MIPS 32 from CPU {}, dtb @ {:#x}", cpu_id, dtb_start); crate::logging::init(); interrupt::init(); memory::init(dtb); timer::init(); - // FIXME: init driver on u540 - #[cfg(not(feature = "board_u540"))] - crate::drivers::init(dtb); - #[cfg(feature = "board_u540")] - unsafe { board::init_external_interrupt(); } + // TODO: initialize device with dtb + // crate::drivers::init(dtb); crate::process::init(); - unsafe { cpu::start_others(hart_mask); } + // TODO: start other CPU + // unsafe { cpu::start_others(hart_mask); } crate::kmain(); } @@ -53,35 +60,8 @@ fn others_main() -> ! { crate::kmain(); } -#[cfg(not(feature = "board_u540"))] -const BOOT_HART_ID: usize = 0; -#[cfg(feature = "board_u540")] -const BOOT_HART_ID: usize = 1; - -/// Constant & Macro for `trap.asm` -#[cfg(target_arch = "riscv32")] -global_asm!(r" - .equ XLENB, 4 - .equ XLENb, 32 - .macro LOAD a1, a2 - lw \a1, \a2*XLENB(sp) - .endm - .macro STORE a1, a2 - sw \a1, \a2*XLENB(sp) - .endm -"); -#[cfg(target_arch = "riscv64")] -global_asm!(r" - .equ XLENB, 8 - .equ XLENb, 64 - .macro LOAD a1, a2 - ld \a1, \a2*XLENB(sp) - .endm - .macro STORE a1, a2 - sd \a1, \a2*XLENB(sp) - .endm -"); - +const BOOT_CPU_ID: usize = 0; global_asm!(include_str!("boot/entry.S")); global_asm!(include_str!("boot/trap.S")); +global_asm!(include_str!("boot/dtb.S")); From c496dd5778cc62516ec0bdf7f5b688c2ddf4f2ea Mon Sep 17 00:00:00 2001 From: Harry Chen Date: Mon, 1 Apr 2019 23:29:50 +0800 Subject: [PATCH 10/85] Fix extra endif in Makefile Signed-off-by: Harry Chen --- kernel/Makefile | 15 ++++++++------- kernel/build.rs | 7 +++---- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/kernel/Makefile b/kernel/Makefile index 9ba6c2c..faff60a 100644 --- a/kernel/Makefile +++ b/kernel/Makefile @@ -42,17 +42,11 @@ build_path := target/$(target)/$(mode) kernel := $(build_path)/rcore kernel_img := $(build_path)/kernel.img bootimage := $(build_path)/bootimage.bin -dtb := src/arch/$(arch)/boot/dts/$(board).dtb bootloader_dir = ../bootloader bootloader := $(bootloader_dir)/target/$(target)/$(mode)/rcore-bootloader bbl_path := $(PWD)/../riscv-pk user_dir := ../user -ifeq ($(arch), aarch64) -board := raspi3 - -ifeq ($(arch), mipsel) -board := malta ### export environments ### export ARCH = $(arch) @@ -60,9 +54,17 @@ export BOARD = $(board) export SMP = $(smp) export DTB = $(dtb) export SFSIMG = $(user_dir)/build/$(arch).qcow2 + +ifeq ($(arch), aarch64) +board := raspi3 export SFSIMG = $(user_dir)/build/$(arch).img +else ifeq ($(arch), mipsel) +board := malta endif +dtb := src/arch/$(arch)/boot/dts/$(board).dtb + + ### qemu options ### qemu_opts := \ -smp cores=$(smp) @@ -108,7 +110,6 @@ qemu_opts += \ -machine $(board) \ -serial null -serial mon:stdio \ -kernel $(kernel_img) -endif else ifeq ($(arch), mipsel) qemu_opts += \ diff --git a/kernel/build.rs b/kernel/build.rs index 9602b9b..be0e3b3 100644 --- a/kernel/build.rs +++ b/kernel/build.rs @@ -2,6 +2,7 @@ extern crate cc; use std::fs::File; use std::io::{Result, Write}; +use std::path::Path; fn main() { println!("cargo:rerun-if-env-changed=LOG"); @@ -19,7 +20,7 @@ fn main() { "riscv64" => { } "mipsel" => { - gen_dtb_asm().unwrap(); + gen_dtb_asm(&arch, &board).unwrap(); } "aarch64" => { } @@ -52,10 +53,8 @@ fn gen_vector_asm() -> Result<()> { } -fn gen_dtb_asm() -> Result<()> { - let arch = std::env::var("ARCH").unwrap(); +fn gen_dtb_asm(arch: &String, board: &String) -> Result<()> { let dtb = std::env::var("DTB").unwrap(); - let board = std::env::var("BOARD").unwrap(); if !Path::new(&dtb).is_file() { panic!("DTB `{}` not found", dtb) From 4ddcdeb00427d08c02d3c94d85083ff291ba5b2c Mon Sep 17 00:00:00 2001 From: Harry Chen Date: Tue, 2 Apr 2019 01:07:08 +0800 Subject: [PATCH 11/85] Complete DTS for qemu-malta Signed-off-by: Harry Chen --- .gitignore | 2 ++ kernel/Cargo.toml | 2 ++ kernel/Makefile | 2 +- kernel/src/arch/mipsel/boot/dts/malta.dts | 44 +++++++++++++++++++++++ 4 files changed, 49 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 446ff27..00657e5 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,8 @@ build target /kernel/src/arch/x86_64/interrupt/vector.asm +/kernel/src/arch/*/boot/dtb.S +*.dtb Cargo.lock !kernel/Cargo.lock diff --git a/kernel/Cargo.toml b/kernel/Cargo.toml index 0dae824..6f32b9d 100644 --- a/kernel/Cargo.toml +++ b/kernel/Cargo.toml @@ -24,6 +24,8 @@ board_u540 = ["sv39", "link_user"] nographic = [] board_raspi3 = ["bcm2837", "link_user"] raspi3_use_generic_timer = ["bcm2837/use_generic_timer"] +# for mipsel qemu malta machine +board_malta = [] # Hard link user program link_user = [] # Run cmdline instead of user shell, useful for automatic testing diff --git a/kernel/Makefile b/kernel/Makefile index c081af4..07b74ce 100644 --- a/kernel/Makefile +++ b/kernel/Makefile @@ -115,7 +115,7 @@ qemu_opts += \ else ifeq ($(arch), mipsel) qemu_opts += \ -machine $(board) \ - -serial null -serial mon:stdio \ + -serial null -serial null -serial mon:stdio \ -kernel $(kernel_img) endif diff --git a/kernel/src/arch/mipsel/boot/dts/malta.dts b/kernel/src/arch/mipsel/boot/dts/malta.dts index e69de29..c68424b 100644 --- a/kernel/src/arch/mipsel/boot/dts/malta.dts +++ b/kernel/src/arch/mipsel/boot/dts/malta.dts @@ -0,0 +1,44 @@ +/dts-v1/; + + +/ { + model = "qemu malta"; + compatible = "qemu,malta"; + #address-cells = <1>; + #size-cells = <1>; + + chosen { + stdio = &uart2; + }; + + aliases { }; + + cpu_intc: interrupt-controller { + compatible = "mti,cpu-interrupt-controller"; + interrupt-controller; + #interrupt-cells = <1>; + }; + + main_memory: memory@0 { + device_type = "memory"; + reg = <0x00000000 0x10000000>; + }; + + uart2: serial@bf000900 { + compatible = "ns16550a"; + reg = <0xbf000900 0x40>; + reg-shift = <3>; + clock-frequency = <1843200>; + /* The CBUS UART is attached to the MIPS CPU INT2 pin, ie interrupt 4 */ + interrupt-parent = <&cpu_intc>; + interrupts = <4>; + }; + + nor0: flash@be000000 { + compatible = "cfi-flash"; + reg = <0xbe000000 0x00400000>; + }; + + // TODO: add graphics and ethernet adapter + +}; From 0a0231599069942db8c3837b0c7a03342e380cef Mon Sep 17 00:00:00 2001 From: Harry Chen Date: Tue, 2 Apr 2019 01:41:48 +0800 Subject: [PATCH 12/85] Add kernel stack for exception handling Signed-off-by: Harry Chen --- .gitignore | 2 ++ kernel/src/arch/mipsel/boot/entry.S | 17 +++++++++++++++-- kernel/src/arch/mipsel/boot/linker.ld | 2 ++ kernel/src/arch/mipsel/boot/trap.S | 20 ++++++++++++++------ 4 files changed, 33 insertions(+), 8 deletions(-) diff --git a/.gitignore b/.gitignore index 00657e5..dc3bbf3 100644 --- a/.gitignore +++ b/.gitignore @@ -13,3 +13,5 @@ Cargo.lock # for eclipse .project + +.vscode diff --git a/kernel/src/arch/mipsel/boot/entry.S b/kernel/src/arch/mipsel/boot/entry.S index 5d2ad14..0d0e70b 100644 --- a/kernel/src/arch/mipsel/boot/entry.S +++ b/kernel/src/arch/mipsel/boot/entry.S @@ -5,9 +5,22 @@ .globl _start _start: - la sp, bootstacktop - la gp, _gp + # setup stack and gp + la sp, bootstacktop + la gp, _gp + # set ebase + la t0, trap_entry + mfc0 t1, 15 # C0_EBASE + or t1, t1, t0 + mtc0 t1, 15 + + # exit bootstrap mode + mfc0 t0, 12 # C0_STATUS + andi t0, t0, 0xFFBFFFFF # set BEV (bit 22) to 0 + mtc0 t0, 12 + + # directly jump to main function b rust_main nop diff --git a/kernel/src/arch/mipsel/boot/linker.ld b/kernel/src/arch/mipsel/boot/linker.ld index 8d09ddb..8570468 100644 --- a/kernel/src/arch/mipsel/boot/linker.ld +++ b/kernel/src/arch/mipsel/boot/linker.ld @@ -17,6 +17,8 @@ SECTIONS *(.text.entry) *(.text .text.*) . = ALIGN(4K); + *(.text.ebase) + . = ALIGN(4K); etext = .; } diff --git a/kernel/src/arch/mipsel/boot/trap.S b/kernel/src/arch/mipsel/boot/trap.S index 4da8de4..f6d891e 100644 --- a/kernel/src/arch/mipsel/boot/trap.S +++ b/kernel/src/arch/mipsel/boot/trap.S @@ -2,8 +2,10 @@ .set noat .set noreorder - .section .text + .section .text.ebase .globl trap_entry + +.org 0x0 trap_entry: # +0x000: TLB-miss vector b general_trap_vec @@ -18,10 +20,9 @@ general_trap_vec: nop # delayslot trap_from_user: - # TODO: load kstack, we can use k0 to store something - # la k0, address_of_kstack - # addiu sp, k0, size_of_kstack - nop + # load kstack, we can use k0 to store something + la k0, kernel_stack + la sp, kernel_stack_top trap_from_kernel: /* @@ -92,7 +93,7 @@ trap_from_kernel: # prepare to call rust_trap jal rust_trap - addiu a0, sp, 16 /* set argument */ + addiu a0, sp, 16 /* set argument (trapframe) */ .globl trap_return trap_return: @@ -148,3 +149,10 @@ trap_return: eret nop + .section .bss.stack + .align 12 #PGSHIFT + .global kernel_stack +kernel_stack: + .space 1024 * 16 # 16KB for kernel stack + .global kernel_stack_top +kernel_stack_top: From 2d5b6948b5e213838e9008e09e5b58fcbe7a55e1 Mon Sep 17 00:00:00 2001 From: Harry Chen Date: Tue, 2 Apr 2019 01:59:50 +0800 Subject: [PATCH 13/85] Pass dtb to driver, remove rv code in io Signed-off-by: Harry Chen --- kernel/src/arch/mipsel/consts.rs | 8 ++------ kernel/src/arch/mipsel/io.rs | 14 +++++--------- kernel/src/arch/mipsel/memory.rs | 32 ++----------------------------- kernel/src/arch/mipsel/mod.rs | 5 ++--- kernel/src/drivers/device_tree.rs | 1 + kernel/src/drivers/mod.rs | 2 +- kernel/src/memory.rs | 2 +- 7 files changed, 14 insertions(+), 50 deletions(-) diff --git a/kernel/src/arch/mipsel/consts.rs b/kernel/src/arch/mipsel/consts.rs index 15d4f8e..78f71db 100644 --- a/kernel/src/arch/mipsel/consts.rs +++ b/kernel/src/arch/mipsel/consts.rs @@ -1,10 +1,6 @@ -// Physical address available on THINPAD: -// [0x80000000, 0x80800000] +/// Platform specific constants -pub const KERNEL_OFFSET: usize = 0xC000_0000; - -#[cfg(target_arch = "riscv32")] -pub const KERNEL_P2_INDEX: usize = (KERNEL_OFFSET >> 12 >> 10) & 0x3ff; +pub const KERNEL_OFFSET: usize = 0x80100000; pub const KERNEL_HEAP_SIZE: usize = 0x00a0_0000; diff --git a/kernel/src/arch/mipsel/io.rs b/kernel/src/arch/mipsel/io.rs index 5f405ee..ca99ad3 100644 --- a/kernel/src/arch/mipsel/io.rs +++ b/kernel/src/arch/mipsel/io.rs @@ -1,5 +1,4 @@ use core::fmt::{Write, Result, Arguments}; -use super::sbi; struct SerialPort; @@ -19,16 +18,12 @@ impl Write for SerialPort { } fn putchar(c: u8) { - if cfg!(feature = "board_u540") { - if c == b'\n' { - sbi::console_putchar(b'\r' as usize); - } - } - sbi::console_putchar(c as usize); + // TODO: output to uart } pub fn getchar() -> char { - let c = sbi::console_getchar() as u8; + // TODO: get char from uart + let c = 0 as u8; match c { 255 => '\0', // null @@ -37,7 +32,8 @@ pub fn getchar() -> char { } pub fn getchar_option() -> Option { - let c = sbi::console_getchar() as isize; + // TODO: get char from uart + let c = 0 as u8; match c { -1 => None, c => Some(c as u8 as char), diff --git a/kernel/src/arch/mipsel/memory.rs b/kernel/src/arch/mipsel/memory.rs index 79ba0d3..a1f09f9 100644 --- a/kernel/src/arch/mipsel/memory.rs +++ b/kernel/src/arch/mipsel/memory.rs @@ -1,26 +1,18 @@ use core::mem; -use riscv::{addr::*, register::sstatus}; use rcore_memory::PAGE_SIZE; use log::*; use crate::memory::{FRAME_ALLOCATOR, init_heap, MemoryAttr, MemorySet, Linear}; use crate::consts::{MEMORY_OFFSET, MEMORY_END, KERNEL_OFFSET}; -use riscv::register::satp; /// Initialize the memory management module -pub fn init(dtb: usize) { - unsafe { sstatus::set_sum(); } // Allow user memory access +pub fn init() { // initialize heap and Frame allocator init_frame_allocator(); init_heap(); - // remap the kernel use 4K page - remap_the_kernel(dtb); } pub fn init_other() { - unsafe { - sstatus::set_sum(); // Allow user memory access - asm!("csrw satp, $0; sfence.vma" :: "r"(SATP) :: "volatile"); - } + // TODO: init other CPU cores } fn init_frame_allocator() { @@ -42,26 +34,6 @@ fn init_frame_allocator() { } } -/// Remap the kernel memory address with 4K page recorded in p1 page table -fn remap_the_kernel(dtb: usize) { - let offset = -(KERNEL_OFFSET as isize - MEMORY_OFFSET as isize); - let mut ms = MemorySet::new_bare(); - ms.push(stext as usize, etext as usize, MemoryAttr::default().execute().readonly(), Linear::new(offset), "text"); - ms.push(sdata as usize, edata as usize, MemoryAttr::default(), Linear::new(offset), "data"); - ms.push(srodata as usize, erodata as usize, MemoryAttr::default().readonly(), Linear::new(offset), "rodata"); - ms.push(bootstack as usize, bootstacktop as usize, MemoryAttr::default(), Linear::new(offset), "stack"); - ms.push(sbss as usize, ebss as usize, MemoryAttr::default(), Linear::new(offset), "bss"); - ms.push(dtb, dtb + super::consts::MAX_DTB_SIZE, MemoryAttr::default().readonly(), Linear::new(offset), "dts"); - // map PLIC for HiFiveU - let offset = -(KERNEL_OFFSET as isize); - ms.push(KERNEL_OFFSET + 0x0C00_2000, KERNEL_OFFSET + 0x0C00_2000 + PAGE_SIZE, MemoryAttr::default(), Linear::new(offset), "plic0"); - ms.push(KERNEL_OFFSET + 0x0C20_2000, KERNEL_OFFSET + 0x0C20_2000 + PAGE_SIZE, MemoryAttr::default(), Linear::new(offset), "plic1"); - unsafe { ms.activate(); } - unsafe { SATP = ms.token(); } - mem::forget(ms); - info!("remap kernel end"); -} - // First core stores its SATP here. // Other cores load it later. static mut SATP: usize = 0; diff --git a/kernel/src/arch/mipsel/mod.rs b/kernel/src/arch/mipsel/mod.rs index a84a54d..bb3d87f 100644 --- a/kernel/src/arch/mipsel/mod.rs +++ b/kernel/src/arch/mipsel/mod.rs @@ -42,10 +42,9 @@ pub extern fn rust_main() -> ! { crate::logging::init(); interrupt::init(); - memory::init(dtb); + memory::init(); timer::init(); - // TODO: initialize device with dtb - // crate::drivers::init(dtb); + crate::drivers::init(dtb_start); crate::process::init(); // TODO: start other CPU diff --git a/kernel/src/drivers/device_tree.rs b/kernel/src/drivers/device_tree.rs index c983e17..656b7e2 100644 --- a/kernel/src/drivers/device_tree.rs +++ b/kernel/src/drivers/device_tree.rs @@ -14,6 +14,7 @@ fn walk_dt_node(dt: &Node) { if compatible == "virtio,mmio" { virtio_probe(dt); } + // TODO: initial other devices (16650, etc.) } if let Ok(bootargs) = dt.prop_str("bootargs") { if bootargs.len() > 0 { diff --git a/kernel/src/drivers/mod.rs b/kernel/src/drivers/mod.rs index 9a1f3e0..b030cdc 100644 --- a/kernel/src/drivers/mod.rs +++ b/kernel/src/drivers/mod.rs @@ -77,7 +77,7 @@ lazy_static! { pub static ref SOCKET_ACTIVITY: Condvar = Condvar::new(); } -#[cfg(any(target_arch = "riscv32", target_arch = "riscv64"))] +#[cfg(any(target_arch = "riscv32", target_arch = "riscv64", target_arch = "mips"))] pub fn init(dtb: usize) { device_tree::init(dtb); } diff --git a/kernel/src/memory.rs b/kernel/src/memory.rs index f48a625..c6a34f0 100644 --- a/kernel/src/memory.rs +++ b/kernel/src/memory.rs @@ -17,7 +17,7 @@ pub type MemorySet = rcore_memory::memory_set::MemorySet; pub type FrameAlloc = bit_allocator::BitAlloc16M; // RISCV has 8M memory -#[cfg(any(target_arch = "riscv32", target_arch = "riscv64"))] +#[cfg(any(target_arch = "riscv32", target_arch = "riscv64", target_arch = "mips"))] pub type FrameAlloc = bit_allocator::BitAlloc4K; // Raspberry Pi 3 has 1G memory From 4e3b2fb80f6cbbfd0c5eae1293b754faf9b31997 Mon Sep 17 00:00:00 2001 From: Harry Chen Date: Tue, 2 Apr 2019 16:52:36 +0800 Subject: [PATCH 14/85] Add support for 16550 serial controller Signed-off-by: Harry Chen --- kernel/src/arch/mipsel/io.rs | 76 +++++++++++++++++++++++++++++------ kernel/src/arch/mipsel/mod.rs | 2 + 2 files changed, 66 insertions(+), 12 deletions(-) diff --git a/kernel/src/arch/mipsel/io.rs b/kernel/src/arch/mipsel/io.rs index ca99ad3..e14c4ec 100644 --- a/kernel/src/arch/mipsel/io.rs +++ b/kernel/src/arch/mipsel/io.rs @@ -1,6 +1,7 @@ use core::fmt::{Write, Result, Arguments}; +use core::ptr::{read_volatile, write_volatile}; -struct SerialPort; +struct SerialPort {}; impl Write for SerialPort { fn write_str(&mut self, s: &str) -> Result { @@ -17,26 +18,40 @@ impl Write for SerialPort { } } +fn write(addr: usize, content: T) { + let cell = (addr) as *mut T; + write_volatile(cell, content); +} + +fn read(addr: usize) -> T { + let cell = (addr) as *const T; + read_volatile(cell); +} + +/// non-blocking version of putchar() fn putchar(c: u8) { - // TODO: output to uart + write(COM1 + COM_TX, c); } +/// blocking version of getchar() pub fn getchar() -> char { - // TODO: get char from uart - let c = 0 as u8; - + loop { + if (read::(COM1 + COM_LSR) & COM_LSR_DATA) == 0 { + break; + } + } + let c = read::(COM1 + COM_RX); match c { 255 => '\0', // null c => c as char, } } +/// non-blocking version of getchar() pub fn getchar_option() -> Option { - // TODO: get char from uart - let c = 0 as u8; - match c { - -1 => None, - c => Some(c as u8 as char), + match read::(COM1 + COM_LSR) & COM_LSR_DATA { + 0 => None, + else => Some(read::(COM1 + COM_RX) as u8 as char), } } @@ -44,5 +59,42 @@ pub fn putfmt(fmt: Arguments) { SerialPort.write_fmt(fmt).unwrap(); } -const TXDATA: *mut u32 = 0x38000000 as *mut u32; -const RXDATA: *mut u32 = 0x38000004 as *mut u32; +pub fn init(serial_base_addr: usize) { + COM1 = serial_base_addr; + // Turn off the FIFO + write(COM1 + COM_FCR, 0 as u8); + // Set speed; requires DLAB latch + write(COM1 + COM_LCR, COM_LCR_DLAB); + write(COM1 + COM_DLL, (115200 / 9600) as u8); + write(COM1 + COM_DLM, 0 as u8); + + // 8 data bits, 1 stop bit, parity off; turn off DLAB latch + write(COM1 + COM_LCR, COM_LCR_WLEN8 & !COM_LCR_DLAB); + + // No modem controls + write(COM1 + COM_MCR, 0 as u8); + // Enable rcv interrupts + write(COM1 + COM_IER, COM_IER_RDI); +} + +static mut COM1: usize = 0; + +const COM_RX :usize = 0; // In: Receive buffer (DLAB=0) +const COM_TX :usize = 0; // Out: Transmit buffer (DLAB=0) +const COM_DLL :usize = 0; // Out: Divisor Latch Low (DLAB=1) +const COM_DLM :usize = 1; // Out: Divisor Latch High (DLAB=1) +const COM_IER :usize = 1; // Out: Interrupt Enable Register +const COM_IER_RDI :u8 = 0x01; // Enable receiver data interrupt +const COM_IIR :usize = 2; // In: Interrupt ID Register +const COM_FCR :usize = 2; // Out: FIFO Control Register +const COM_LCR :usize = 3; // Out: Line Control Register +const COM_LCR_DLAB :u8 = 0x80; // Divisor latch access bit +const COM_LCR_WLEN8 :u8 = 0x03; // Wordlength: 8 bits +const COM_MCR :usize = 4; // Out: Modem Control Register +const COM_MCR_RTS :u8 = 0x02; // RTS complement +const COM_MCR_DTR :u8 = 0x01; // DTR complement +const COM_MCR_OUT2 :u8 = 0x08; // Out2 complement +const COM_LSR :usize = 5; // In: Line Status Register +const COM_LSR_DATA :u8 = 0x01; // Data available +const COM_LSR_TXRDY :u8 = 0x20; // Transmit buffer avail +const COM_LSR_TSRE :u8 = 0x40; // Transmitter off diff --git a/kernel/src/arch/mipsel/mod.rs b/kernel/src/arch/mipsel/mod.rs index bb3d87f..9681b06 100644 --- a/kernel/src/arch/mipsel/mod.rs +++ b/kernel/src/arch/mipsel/mod.rs @@ -38,6 +38,8 @@ pub extern fn rust_main() -> ! { unsafe { memory::clear_bss(); } + crate::io::init(); + println!("Hello MIPS 32 from CPU {}, dtb @ {:#x}", cpu_id, dtb_start); crate::logging::init(); From 85245c4e21c3eac39878dff1a67742ecc50c0373 Mon Sep 17 00:00:00 2001 From: Harry Chen Date: Wed, 3 Apr 2019 08:46:22 +0800 Subject: [PATCH 15/85] Finish serial initialization Signed-off-by: Harry Chen --- kernel/src/arch/mipsel/interrupt.rs | 4 ---- kernel/src/arch/mipsel/io.rs | 6 +++--- 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/kernel/src/arch/mipsel/interrupt.rs b/kernel/src/arch/mipsel/interrupt.rs index f6bea8a..b6957bf 100644 --- a/kernel/src/arch/mipsel/interrupt.rs +++ b/kernel/src/arch/mipsel/interrupt.rs @@ -74,9 +74,6 @@ pub extern fn rust_trap(tf: &mut TrapFrame) { fn external() { // TODO - #[cfg(feature = "board_u540")] - unsafe { super::board::handle_external_interrupt(); } - // true means handled, false otherwise let handlers = [try_process_serial, try_process_drivers]; for handler in handlers.iter() { @@ -87,7 +84,6 @@ fn external() { } fn try_process_serial() -> bool { - // TODO match super::io::getchar_option() { Some(ch) => { crate::trap::serial(ch); diff --git a/kernel/src/arch/mipsel/io.rs b/kernel/src/arch/mipsel/io.rs index e14c4ec..50c224d 100644 --- a/kernel/src/arch/mipsel/io.rs +++ b/kernel/src/arch/mipsel/io.rs @@ -59,8 +59,7 @@ pub fn putfmt(fmt: Arguments) { SerialPort.write_fmt(fmt).unwrap(); } -pub fn init(serial_base_addr: usize) { - COM1 = serial_base_addr; +pub fn init() { // Turn off the FIFO write(COM1 + COM_FCR, 0 as u8); // Set speed; requires DLAB latch @@ -77,7 +76,8 @@ pub fn init(serial_base_addr: usize) { write(COM1 + COM_IER, COM_IER_RDI); } -static mut COM1: usize = 0; +#[cfg(feature = "board_malta")] +const COM1 :usize = 0xbf000900; // 16550 Base Address const COM_RX :usize = 0; // In: Receive buffer (DLAB=0) const COM_TX :usize = 0; // Out: Transmit buffer (DLAB=0) From 8dff9f1b1444ac3df2e428d5fc7eb7e8c9a0387c Mon Sep 17 00:00:00 2001 From: Harry Chen Date: Wed, 3 Apr 2019 12:07:58 +0800 Subject: [PATCH 16/85] Re-orgnize drivers for mipsel, extract FBConsole driver to common directory Signed-off-by: Harry Chen --- kernel/src/arch/aarch64/driver/mod.rs | 1 + kernel/src/arch/mipsel/board/malta/fb.rs | 7 ++ kernel/src/arch/mipsel/board/malta/mod.rs | 19 +++ kernel/src/arch/mipsel/board/malta/serial.rs | 114 ++++++++++++++++++ kernel/src/arch/mipsel/board/thinpad/mod.rs | 20 +++ kernel/src/arch/mipsel/driver/mod.rs | 16 +++ kernel/src/arch/mipsel/io.rs | 108 +++-------------- kernel/src/arch/mipsel/mod.rs | 15 ++- .../driver => drivers}/console/color.rs | 0 .../console/fonts/font8x16.rs | 0 .../driver => drivers}/console/fonts/mod.rs | 0 .../aarch64/driver => drivers}/console/mod.rs | 0 12 files changed, 209 insertions(+), 91 deletions(-) create mode 100644 kernel/src/arch/mipsel/board/malta/fb.rs create mode 100644 kernel/src/arch/mipsel/board/malta/mod.rs create mode 100644 kernel/src/arch/mipsel/board/malta/serial.rs create mode 100644 kernel/src/arch/mipsel/board/thinpad/mod.rs create mode 100644 kernel/src/arch/mipsel/driver/mod.rs rename kernel/src/{arch/aarch64/driver => drivers}/console/color.rs (100%) rename kernel/src/{arch/aarch64/driver => drivers}/console/fonts/font8x16.rs (100%) rename kernel/src/{arch/aarch64/driver => drivers}/console/fonts/mod.rs (100%) rename kernel/src/{arch/aarch64/driver => drivers}/console/mod.rs (100%) diff --git a/kernel/src/arch/aarch64/driver/mod.rs b/kernel/src/arch/aarch64/driver/mod.rs index 9c29662..a100c2b 100644 --- a/kernel/src/arch/aarch64/driver/mod.rs +++ b/kernel/src/arch/aarch64/driver/mod.rs @@ -5,6 +5,7 @@ use once::*; pub use self::board::fb; pub use self::board::serial; +#[path = "../../../drivers/console/mod.rs"] pub mod console; /// Initialize ARM64 common drivers diff --git a/kernel/src/arch/mipsel/board/malta/fb.rs b/kernel/src/arch/mipsel/board/malta/fb.rs new file mode 100644 index 0000000..89c4321 --- /dev/null +++ b/kernel/src/arch/mipsel/board/malta/fb.rs @@ -0,0 +1,7 @@ +lazy_static! { + pub static ref FRAME_BUFFER: Mutex> = Mutex::new(None); +} + +pub struct FramebufferInfo {} + +pub enum ColorDepth {} \ No newline at end of file diff --git a/kernel/src/arch/mipsel/board/malta/mod.rs b/kernel/src/arch/mipsel/board/malta/mod.rs new file mode 100644 index 0000000..ae61c69 --- /dev/null +++ b/kernel/src/arch/mipsel/board/malta/mod.rs @@ -0,0 +1,19 @@ +use once::*; + +pub mod serial; +pub mod fb; +#[path = "../../../../drivers/console/mod.rs"] +pub mod console; + +/// Initialize serial port first +pub fn init_serial_early() { + assert_has_not_been_called!("board::init must be called only once"); + serial::init(); + println!("Hello QEMU Malta!"); +} + +/// Initialize other board drivers +pub fn init_driver() { + // TODO: add possibly more drivers + // timer::init(); +} \ No newline at end of file diff --git a/kernel/src/arch/mipsel/board/malta/serial.rs b/kernel/src/arch/mipsel/board/malta/serial.rs new file mode 100644 index 0000000..4a20383 --- /dev/null +++ b/kernel/src/arch/mipsel/board/malta/serial.rs @@ -0,0 +1,114 @@ +use core::fmt::{Write, Result, Arguments}; +use core::ptr::{read_volatile, write_volatile}; + +struct SerialPort {}; + +impl SerialPort { + fn new() -> SerialPort { + SerialPort { } + } +} + +impl Write for SerialPort { + fn write_str(&mut self, s: &str) -> Result { + for c in s.bytes() { + if c == 127 { + putchar(8); + putchar(b' '); + putchar(8); + } else { + putchar(c); + } + } + Ok(()) + } +} + +fn write(addr: usize, content: T) { + let cell = (addr) as *mut T; + write_volatile(cell, content); +} + +fn read(addr: usize) -> T { + let cell = (addr) as *const T; + read_volatile(cell); +} + +/// non-blocking version of putchar() +fn putchar(c: u8) { + write(COM1 + COM_TX, c); +} + +/// blocking version of getchar() +pub fn getchar() -> char { + loop { + if (read::(COM1 + COM_LSR) & COM_LSR_DATA) == 0 { + break; + } + } + let c = read::(COM1 + COM_RX); + match c { + 255 => '\0', // null + c => c as char, + } +} + +/// non-blocking version of getchar() +pub fn getchar_option() -> Option { + match read::(COM1 + COM_LSR) & COM_LSR_DATA { + 0 => None, + else => Some(read::(COM1 + COM_RX) as u8 as char), + } +} + +pub fn putfmt(fmt: Arguments) { + SerialPort.write_fmt(fmt).unwrap(); +} + +pub fn init() { + // Turn off the FIFO + write(COM1 + COM_FCR, 0 as u8); + // Set speed; requires DLAB latch + write(COM1 + COM_LCR, COM_LCR_DLAB); + write(COM1 + COM_DLL, (115200 / 9600) as u8); + write(COM1 + COM_DLM, 0 as u8); + + // 8 data bits, 1 stop bit, parity off; turn off DLAB latch + write(COM1 + COM_LCR, COM_LCR_WLEN8 & !COM_LCR_DLAB); + + // No modem controls + write(COM1 + COM_MCR, 0 as u8); + // Enable rcv interrupts + write(COM1 + COM_IER, COM_IER_RDI); +} + +const COM1 :usize = 0xbf000900; // 16550 Base Address + +const COM_RX :usize = 0; // In: Receive buffer (DLAB=0) +const COM_TX :usize = 0; // Out: Transmit buffer (DLAB=0) +const COM_DLL :usize = 0; // Out: Divisor Latch Low (DLAB=1) +const COM_DLM :usize = 1; // Out: Divisor Latch High (DLAB=1) +const COM_IER :usize = 1; // Out: Interrupt Enable Register +const COM_IER_RDI :u8 = 0x01; // Enable receiver data interrupt +const COM_IIR :usize = 2; // In: Interrupt ID Register +const COM_FCR :usize = 2; // Out: FIFO Control Register +const COM_LCR :usize = 3; // Out: Line Control Register +const COM_LCR_DLAB :u8 = 0x80; // Divisor latch access bit +const COM_LCR_WLEN8 :u8 = 0x03; // Wordlength: 8 bits +const COM_MCR :usize = 4; // Out: Modem Control Register +const COM_MCR_RTS :u8 = 0x02; // RTS complement +const COM_MCR_DTR :u8 = 0x01; // DTR complement +const COM_MCR_OUT2 :u8 = 0x08; // Out2 complement +const COM_LSR :usize = 5; // In: Line Status Register +const COM_LSR_DATA :u8 = 0x01; // Data available +const COM_LSR_TXRDY :u8 = 0x20; // Transmit buffer avail +const COM_LSR_TSRE :u8 = 0x40; // Transmitter off + + +lazy_static! { + pub static ref SERIAL_PORT: Mutex = Mutex::new(SerialPort::new()); +} + +pub fn init() { + SERIAL_PORT.lock().init(); +} \ No newline at end of file diff --git a/kernel/src/arch/mipsel/board/thinpad/mod.rs b/kernel/src/arch/mipsel/board/thinpad/mod.rs new file mode 100644 index 0000000..1277ed7 --- /dev/null +++ b/kernel/src/arch/mipsel/board/thinpad/mod.rs @@ -0,0 +1,20 @@ +use once::*; + +pub mod serial; +pub mod fb; +#[path = "../../../../drivers/console/mod.rs"] +pub mod console; + +/// Initialize serial port first +pub fn init_serial_early() { + assert_has_not_been_called!("board::init must be called only once"); + serial::init(); + println!("Hello ThinPad!"); +} + +/// Initialize other board drivers +pub fn init_driver() { + // TODO: add possibly more drivers + // timer::init(); + console::init(); +} \ No newline at end of file diff --git a/kernel/src/arch/mipsel/driver/mod.rs b/kernel/src/arch/mipsel/driver/mod.rs new file mode 100644 index 0000000..67c4009 --- /dev/null +++ b/kernel/src/arch/mipsel/driver/mod.rs @@ -0,0 +1,16 @@ +//! mipsel drivers + +use super::board; +use once::*; + +pub use self::board::serial; +pub use self::board::fb; +#[path = "../../../drivers/console/mod.rs"] +pub mod console; + +/// Initialize common drivers +pub fn init() { + assert_has_not_been_called!("driver::init must be called only once"); + board::init_driver(); + console::init(); +} diff --git a/kernel/src/arch/mipsel/io.rs b/kernel/src/arch/mipsel/io.rs index 50c224d..b184a57 100644 --- a/kernel/src/arch/mipsel/io.rs +++ b/kernel/src/arch/mipsel/io.rs @@ -1,100 +1,30 @@ -use core::fmt::{Write, Result, Arguments}; -use core::ptr::{read_volatile, write_volatile}; +//! Input/output for mipsel. -struct SerialPort {}; +use super::driver::console::CONSOLE; +use super::driver::serial::*; +use core::fmt::{Arguments, Write}; -impl Write for SerialPort { - fn write_str(&mut self, s: &str) -> Result { - for c in s.bytes() { - if c == 127 { - putchar(8); - putchar(b' '); - putchar(8); - } else { - putchar(c); - } - } - Ok(()) - } -} - -fn write(addr: usize, content: T) { - let cell = (addr) as *mut T; - write_volatile(cell, content); -} - -fn read(addr: usize) -> T { - let cell = (addr) as *const T; - read_volatile(cell); -} - -/// non-blocking version of putchar() -fn putchar(c: u8) { - write(COM1 + COM_TX, c); -} - -/// blocking version of getchar() pub fn getchar() -> char { - loop { - if (read::(COM1 + COM_LSR) & COM_LSR_DATA) == 0 { - break; - } - } - let c = read::(COM1 + COM_RX); - match c { - 255 => '\0', // null - c => c as char, - } + unsafe { SERIAL_PORT.force_unlock() } + SERIAL_PORT.lock().getchar() } -/// non-blocking version of getchar() -pub fn getchar_option() -> Option { - match read::(COM1 + COM_LSR) & COM_LSR_DATA { - 0 => None, - else => Some(read::(COM1 + COM_RX) as u8 as char), - } +pub fn getchar_option() -> Option { + unsafe { SERIAL_PORT.force_unlock() } + SERIAL_PORT.lock().getchar_option() } pub fn putfmt(fmt: Arguments) { - SerialPort.write_fmt(fmt).unwrap(); -} - -pub fn init() { - // Turn off the FIFO - write(COM1 + COM_FCR, 0 as u8); - // Set speed; requires DLAB latch - write(COM1 + COM_LCR, COM_LCR_DLAB); - write(COM1 + COM_DLL, (115200 / 9600) as u8); - write(COM1 + COM_DLM, 0 as u8); + unsafe { SERIAL_PORT.force_unlock() } + SERIAL_PORT.lock().write_fmt(fmt).unwrap(); - // 8 data bits, 1 stop bit, parity off; turn off DLAB latch - write(COM1 + COM_LCR, COM_LCR_WLEN8 & !COM_LCR_DLAB); - - // No modem controls - write(COM1 + COM_MCR, 0 as u8); - // Enable rcv interrupts - write(COM1 + COM_IER, COM_IER_RDI); + unsafe { CONSOLE.force_unlock() } + if let Some(console) = CONSOLE.lock().as_mut() { + console.write_fmt(fmt).unwrap(); + } } -#[cfg(feature = "board_malta")] -const COM1 :usize = 0xbf000900; // 16550 Base Address - -const COM_RX :usize = 0; // In: Receive buffer (DLAB=0) -const COM_TX :usize = 0; // Out: Transmit buffer (DLAB=0) -const COM_DLL :usize = 0; // Out: Divisor Latch Low (DLAB=1) -const COM_DLM :usize = 1; // Out: Divisor Latch High (DLAB=1) -const COM_IER :usize = 1; // Out: Interrupt Enable Register -const COM_IER_RDI :u8 = 0x01; // Enable receiver data interrupt -const COM_IIR :usize = 2; // In: Interrupt ID Register -const COM_FCR :usize = 2; // Out: FIFO Control Register -const COM_LCR :usize = 3; // Out: Line Control Register -const COM_LCR_DLAB :u8 = 0x80; // Divisor latch access bit -const COM_LCR_WLEN8 :u8 = 0x03; // Wordlength: 8 bits -const COM_MCR :usize = 4; // Out: Modem Control Register -const COM_MCR_RTS :u8 = 0x02; // RTS complement -const COM_MCR_DTR :u8 = 0x01; // DTR complement -const COM_MCR_OUT2 :u8 = 0x08; // Out2 complement -const COM_LSR :usize = 5; // In: Line Status Register -const COM_LSR_DATA :u8 = 0x01; // Data available -const COM_LSR_TXRDY :u8 = 0x20; // Transmit buffer avail -const COM_LSR_TSRE :u8 = 0x40; // Transmitter off +pub fn putchar(c: u8) { + unsafe { SERIAL_PORT.force_unlock() } + SERIAL_PORT.lock().putchar(c); +} diff --git a/kernel/src/arch/mipsel/mod.rs b/kernel/src/arch/mipsel/mod.rs index 9681b06..ca51a72 100644 --- a/kernel/src/arch/mipsel/mod.rs +++ b/kernel/src/arch/mipsel/mod.rs @@ -8,11 +8,20 @@ pub mod consts; pub mod cpu; pub mod syscall; pub mod rand; +pub mod driver; use log::*; use mips::registers; use mips::instructions; +#[cfg(feature = "board_malta")] +#[path = "board/malta/mod.rs"] +pub mod board; + +#[cfg(feature = "board_thinpad")] +#[path = "board/thinpad/mod.rs"] +pub mod board; + extern "C" { fn _dtb_start(); fn _dtb_end(); @@ -38,14 +47,16 @@ pub extern fn rust_main() -> ! { unsafe { memory::clear_bss(); } - crate::io::init(); + board::init_serial_early(); + driver::init(); println!("Hello MIPS 32 from CPU {}, dtb @ {:#x}", cpu_id, dtb_start); - crate::logging::init(); interrupt::init(); memory::init(); timer::init(); + + crate::logging::init(); crate::drivers::init(dtb_start); crate::process::init(); diff --git a/kernel/src/arch/aarch64/driver/console/color.rs b/kernel/src/drivers/console/color.rs similarity index 100% rename from kernel/src/arch/aarch64/driver/console/color.rs rename to kernel/src/drivers/console/color.rs diff --git a/kernel/src/arch/aarch64/driver/console/fonts/font8x16.rs b/kernel/src/drivers/console/fonts/font8x16.rs similarity index 100% rename from kernel/src/arch/aarch64/driver/console/fonts/font8x16.rs rename to kernel/src/drivers/console/fonts/font8x16.rs diff --git a/kernel/src/arch/aarch64/driver/console/fonts/mod.rs b/kernel/src/drivers/console/fonts/mod.rs similarity index 100% rename from kernel/src/arch/aarch64/driver/console/fonts/mod.rs rename to kernel/src/drivers/console/fonts/mod.rs diff --git a/kernel/src/arch/aarch64/driver/console/mod.rs b/kernel/src/drivers/console/mod.rs similarity index 100% rename from kernel/src/arch/aarch64/driver/console/mod.rs rename to kernel/src/drivers/console/mod.rs From 015cc72aa42d223111436b579d14e8b823437205 Mon Sep 17 00:00:00 2001 From: Harry Chen Date: Wed, 3 Apr 2019 13:53:34 +0800 Subject: [PATCH 17/85] Fix malta drivers Signed-off-by: Harry Chen --- kernel/Cargo.toml | 6 +- kernel/Makefile | 4 +- kernel/src/arch/mipsel/board/malta/fb.rs | 2 + kernel/src/arch/mipsel/board/malta/mod.rs | 2 +- kernel/src/arch/mipsel/board/malta/serial.rs | 115 ++++++++++--------- 5 files changed, 70 insertions(+), 59 deletions(-) diff --git a/kernel/Cargo.toml b/kernel/Cargo.toml index 6f32b9d..936a813 100644 --- a/kernel/Cargo.toml +++ b/kernel/Cargo.toml @@ -13,7 +13,9 @@ authors = [ "chenqiuhao ", "maoyuchaxue ", "Jiajie Chen ", - "chyyuu " + "chyyuu ", + "Shengqi Chen ", + "Yuhao Zhou " ] [features] @@ -26,6 +28,8 @@ board_raspi3 = ["bcm2837", "link_user"] raspi3_use_generic_timer = ["bcm2837/use_generic_timer"] # for mipsel qemu malta machine board_malta = [] +# for thinpad +board_thinpad = [] # Hard link user program link_user = [] # Run cmdline instead of user shell, useful for automatic testing diff --git a/kernel/Makefile b/kernel/Makefile index 07b74ce..19d0c88 100644 --- a/kernel/Makefile +++ b/kernel/Makefile @@ -113,11 +113,13 @@ qemu_opts += \ -kernel $(kernel_img) else ifeq ($(arch), mipsel) +ifeq ($(board), malta) qemu_opts += \ -machine $(board) \ - -serial null -serial null -serial mon:stdio \ + -serial none -serial none -serial mon:stdio \ -kernel $(kernel_img) endif +endif ifdef d qemu_opts += -d $(d) diff --git a/kernel/src/arch/mipsel/board/malta/fb.rs b/kernel/src/arch/mipsel/board/malta/fb.rs index 89c4321..7023e5e 100644 --- a/kernel/src/arch/mipsel/board/malta/fb.rs +++ b/kernel/src/arch/mipsel/board/malta/fb.rs @@ -2,6 +2,8 @@ lazy_static! { pub static ref FRAME_BUFFER: Mutex> = Mutex::new(None); } +pub struct Framebuffer {} + pub struct FramebufferInfo {} pub enum ColorDepth {} \ No newline at end of file diff --git a/kernel/src/arch/mipsel/board/malta/mod.rs b/kernel/src/arch/mipsel/board/malta/mod.rs index ae61c69..0a3f750 100644 --- a/kernel/src/arch/mipsel/board/malta/mod.rs +++ b/kernel/src/arch/mipsel/board/malta/mod.rs @@ -8,7 +8,7 @@ pub mod console; /// Initialize serial port first pub fn init_serial_early() { assert_has_not_been_called!("board::init must be called only once"); - serial::init(); + serial::init(0xbf000900); println!("Hello QEMU Malta!"); } diff --git a/kernel/src/arch/mipsel/board/malta/serial.rs b/kernel/src/arch/mipsel/board/malta/serial.rs index 4a20383..2ee0a4e 100644 --- a/kernel/src/arch/mipsel/board/malta/serial.rs +++ b/kernel/src/arch/mipsel/board/malta/serial.rs @@ -1,23 +1,75 @@ use core::fmt::{Write, Result, Arguments}; use core::ptr::{read_volatile, write_volatile}; -struct SerialPort {}; +struct SerialPort { + base: usize +} impl SerialPort { fn new() -> SerialPort { SerialPort { } } + + pub fn init(&mut self, base: usize) { + self.base = base; + // Turn off the FIFO + write(self.base + COM_FCR, 0 as u8); + // Set speed; requires DLAB latch + write(self.base + COM_LCR, COM_LCR_DLAB); + write(self.base + COM_DLL, (115200 / 9600) as u8); + write(self.base + COM_DLM, 0 as u8); + + // 8 data bits, 1 stop bit, parity off; turn off DLAB latch + write(self.base + COM_LCR, COM_LCR_WLEN8 & !COM_LCR_DLAB); + + // No modem controls + write(self.base + COM_MCR, 0 as u8); + // Enable rcv interrupts + write(self.base + COM_IER, COM_IER_RDI); + } + + /// non-blocking version of putchar() + fn putchar(&mut self, c: u8) { + write(self.base + COM_TX, c); + } + + /// blocking version of getchar() + pub fn getchar(&mut self) -> char { + loop { + if (read::(self.base + COM_LSR) & COM_LSR_DATA) == 0 { + break; + } + } + let c = read::(self.base + COM_RX); + match c { + 255 => '\0', // null + c => c as char, + } + } + + /// non-blocking version of getchar() + pub fn getchar_option(&mut self) -> Option { + match read::(self.base + COM_LSR) & COM_LSR_DATA { + 0 => None, + _ => Some(read::(self.base + COM_RX) as u8 as char), + } + } + + pub fn putfmt(&mut self, fmt: Arguments) { + self.write_fmt(fmt).unwrap(); + } + } impl Write for SerialPort { fn write_str(&mut self, s: &str) -> Result { for c in s.bytes() { if c == 127 { - putchar(8); - putchar(b' '); - putchar(8); + self.putchar(8); + self.putchar(b' '); + self.putchar(8); } else { - putchar(c); + self.putchar(c); } } Ok(()) @@ -34,55 +86,6 @@ fn read(addr: usize) -> T { read_volatile(cell); } -/// non-blocking version of putchar() -fn putchar(c: u8) { - write(COM1 + COM_TX, c); -} - -/// blocking version of getchar() -pub fn getchar() -> char { - loop { - if (read::(COM1 + COM_LSR) & COM_LSR_DATA) == 0 { - break; - } - } - let c = read::(COM1 + COM_RX); - match c { - 255 => '\0', // null - c => c as char, - } -} - -/// non-blocking version of getchar() -pub fn getchar_option() -> Option { - match read::(COM1 + COM_LSR) & COM_LSR_DATA { - 0 => None, - else => Some(read::(COM1 + COM_RX) as u8 as char), - } -} - -pub fn putfmt(fmt: Arguments) { - SerialPort.write_fmt(fmt).unwrap(); -} - -pub fn init() { - // Turn off the FIFO - write(COM1 + COM_FCR, 0 as u8); - // Set speed; requires DLAB latch - write(COM1 + COM_LCR, COM_LCR_DLAB); - write(COM1 + COM_DLL, (115200 / 9600) as u8); - write(COM1 + COM_DLM, 0 as u8); - - // 8 data bits, 1 stop bit, parity off; turn off DLAB latch - write(COM1 + COM_LCR, COM_LCR_WLEN8 & !COM_LCR_DLAB); - - // No modem controls - write(COM1 + COM_MCR, 0 as u8); - // Enable rcv interrupts - write(COM1 + COM_IER, COM_IER_RDI); -} - -const COM1 :usize = 0xbf000900; // 16550 Base Address const COM_RX :usize = 0; // In: Receive buffer (DLAB=0) const COM_TX :usize = 0; // Out: Transmit buffer (DLAB=0) @@ -109,6 +112,6 @@ lazy_static! { pub static ref SERIAL_PORT: Mutex = Mutex::new(SerialPort::new()); } -pub fn init() { - SERIAL_PORT.lock().init(); +pub fn init(base: usize) { + SERIAL_PORT.lock().init(base); } \ No newline at end of file From 6245d86a276104bc569e874976f62ffcb91da932 Mon Sep 17 00:00:00 2001 From: Harry Chen Date: Wed, 3 Apr 2019 15:52:34 +0800 Subject: [PATCH 18/85] Move dts to board dir, fix some import error Signed-off-by: Harry Chen --- kernel/Makefile | 16 +++++++++------- .../dts/malta.dts => board/malta/device.dts} | 0 kernel/src/arch/mipsel/board/malta/fb.rs | 4 ++++ kernel/src/arch/mipsel/board/malta/serial.rs | 7 ++++++- kernel/src/arch/mipsel/interrupt.rs | 4 ++-- kernel/src/arch/mipsel/io.rs | 2 +- kernel/src/arch/mipsel/mod.rs | 2 +- 7 files changed, 23 insertions(+), 12 deletions(-) rename kernel/src/arch/mipsel/{boot/dts/malta.dts => board/malta/device.dts} (100%) diff --git a/kernel/Makefile b/kernel/Makefile index 19d0c88..2ab9b70 100644 --- a/kernel/Makefile +++ b/kernel/Makefile @@ -49,20 +49,22 @@ user_dir := ../user ### export environments ### -export ARCH = $(arch) -export BOARD = $(board) -export SMP = $(smp) -export DTB = $(dtb) export SFSIMG = $(user_dir)/build/$(arch).qcow2 ifeq ($(arch), aarch64) board := raspi3 export SFSIMG = $(user_dir)/build/$(arch).img -else ifeq ($(arch), mipsel) -board := malta endif -dtb := src/arch/$(arch)/boot/dts/$(board).dtb +# currently only mipsel architecture needs DTB linked to the kernel +ifeq ($(arch), mipsel) +dtb := src/arch/$(arch)/board/$(board)/device.dtb +endif + +export ARCH = $(arch) +export BOARD = $(board) +export SMP = $(smp) +export DTB = $(dtb) ### qemu options ### diff --git a/kernel/src/arch/mipsel/boot/dts/malta.dts b/kernel/src/arch/mipsel/board/malta/device.dts similarity index 100% rename from kernel/src/arch/mipsel/boot/dts/malta.dts rename to kernel/src/arch/mipsel/board/malta/device.dts diff --git a/kernel/src/arch/mipsel/board/malta/fb.rs b/kernel/src/arch/mipsel/board/malta/fb.rs index 7023e5e..f466bfa 100644 --- a/kernel/src/arch/mipsel/board/malta/fb.rs +++ b/kernel/src/arch/mipsel/board/malta/fb.rs @@ -1,3 +1,7 @@ +//! stub frame buffer driver for malta board + +use spin::Mutex; + lazy_static! { pub static ref FRAME_BUFFER: Mutex> = Mutex::new(None); } diff --git a/kernel/src/arch/mipsel/board/malta/serial.rs b/kernel/src/arch/mipsel/board/malta/serial.rs index 2ee0a4e..b9b7fe0 100644 --- a/kernel/src/arch/mipsel/board/malta/serial.rs +++ b/kernel/src/arch/mipsel/board/malta/serial.rs @@ -1,5 +1,8 @@ +//! 16550 serial adapter driver for malta board + use core::fmt::{Write, Result, Arguments}; use core::ptr::{read_volatile, write_volatile}; +use spin::Mutex; struct SerialPort { base: usize @@ -7,7 +10,9 @@ struct SerialPort { impl SerialPort { fn new() -> SerialPort { - SerialPort { } + SerialPort { + base: 0 + } } pub fn init(&mut self, base: usize) { diff --git a/kernel/src/arch/mipsel/interrupt.rs b/kernel/src/arch/mipsel/interrupt.rs index b6957bf..f78657a 100644 --- a/kernel/src/arch/mipsel/interrupt.rs +++ b/kernel/src/arch/mipsel/interrupt.rs @@ -1,5 +1,5 @@ -use mips::interrupts::*; -use mips::registers::*; +use mips::interrupts; +use mips::registers::cp0; use crate::drivers::DRIVERS; pub use self::context::*; use log::*; diff --git a/kernel/src/arch/mipsel/io.rs b/kernel/src/arch/mipsel/io.rs index b184a57..2012a62 100644 --- a/kernel/src/arch/mipsel/io.rs +++ b/kernel/src/arch/mipsel/io.rs @@ -9,7 +9,7 @@ pub fn getchar() -> char { SERIAL_PORT.lock().getchar() } -pub fn getchar_option() -> Option { +pub fn getchar_option() -> Option { unsafe { SERIAL_PORT.force_unlock() } SERIAL_PORT.lock().getchar_option() } diff --git a/kernel/src/arch/mipsel/mod.rs b/kernel/src/arch/mipsel/mod.rs index ca51a72..e8c3fe0 100644 --- a/kernel/src/arch/mipsel/mod.rs +++ b/kernel/src/arch/mipsel/mod.rs @@ -11,7 +11,7 @@ pub mod rand; pub mod driver; use log::*; -use mips::registers; +use mips::registers::cp0; use mips::instructions; #[cfg(feature = "board_malta")] From f394f0fccb4153901caf0c09ea8da541326e86a6 Mon Sep 17 00:00:00 2001 From: Harry Chen Date: Wed, 3 Apr 2019 16:50:45 +0800 Subject: [PATCH 19/85] Add DTS for thinpad Signed-off-by: Harry Chen --- .../src/arch/mipsel/board/thinpad/device.dts | 85 +++++++++++++++++++ 1 file changed, 85 insertions(+) create mode 100644 kernel/src/arch/mipsel/board/thinpad/device.dts diff --git a/kernel/src/arch/mipsel/board/thinpad/device.dts b/kernel/src/arch/mipsel/board/thinpad/device.dts new file mode 100644 index 0000000..5a771c9 --- /dev/null +++ b/kernel/src/arch/mipsel/board/thinpad/device.dts @@ -0,0 +1,85 @@ +/dts-v1/; + + +/ { + model = "thinpad trivialmips"; + compatible = "tsinghua,thinpad"; + #address-cells = <1>; + #size-cells = <1>; + + chosen { + stdio = &uart; + bootargs = ""; + }; + + aliases { }; + + cpu_intc: interrupt-controller { + compatible = "mti,cpu-interrupt-controller"; + interrupt-controller; + #interrupt-cells = <1>; + }; + + memory: memory@80000000 { + device_type = "memory"; + reg = <0x80000000 0x00800000>; + }; + + bus: trivial_bus@a0000000 { + compatible = "thinpad,bus"; + reg = <0xa0000000 0x800000>; + #address-cells = <1>; + #size-cells = <1>; + ranges; + + flash: flash@a1000000 { + compatible = "cfi-flash"; + reg = <0xa1000000 0x00800000>; + }; + + framebuffer: framebuffer@a2000000 { + compatible = "thinpad,framebuffer"; + reg = <0xa2000000 0x75300 + 0xa2075300 0x4>; + }; + + uart: serial@a3000000 { + compatible = "thinpad,uart"; + reg = <0xa3000000 0x1 + 0xa3000004 0x1>; + clock-frequency = <115200>; + interrupt-parent = <&cpu_intc>; + interrupts = <1>; + }; + + timer: gpio@a4000000 { + compatible = "thinpad,timer"; + reg = <0xa400000 0x8>; + }; + + eth: ethernet@a5000000 { + compatible = "davicom,dm9000"; + reg = <0xa5000000 0x2 + 0xa5000004 0x2>; + interrupt-parent = <&cpu_intc>; + interrupts = <2>; + davicom,no-eeprom; + mac-address = [00 0a 2d 98 01 29]; + }; + + gpio: gpio@a6000000 { + compatible = "thinpad,gpio"; + reg = <0xa6000000 0x2 + 0xa6000004 0x2 + 0xa6000008 0x2>; + reg-io-width = <2>; + }; + + usb: usb@a7000000 { + compatible = "cypress,sl811"; + reg = <0xa7000000 0x1 + 0xa7000004 0x1>; + }; + }; + +}; From 0acb65ff747a35e34923d8dfcc01b456e173dce9 Mon Sep 17 00:00:00 2001 From: Harry Chen Date: Wed, 3 Apr 2019 16:58:52 +0800 Subject: [PATCH 20/85] Add driver for thinpad Signed-off-by: Harry Chen --- kernel/src/arch/mipsel/board/thinpad/fb.rs | 232 ++++++++++++++++++ kernel/src/arch/mipsel/board/thinpad/mod.rs | 3 +- .../src/arch/mipsel/board/thinpad/serial.rs | 94 +++++++ 3 files changed, 327 insertions(+), 2 deletions(-) create mode 100644 kernel/src/arch/mipsel/board/thinpad/fb.rs create mode 100644 kernel/src/arch/mipsel/board/thinpad/serial.rs diff --git a/kernel/src/arch/mipsel/board/thinpad/fb.rs b/kernel/src/arch/mipsel/board/thinpad/fb.rs new file mode 100644 index 0000000..ff3b31f --- /dev/null +++ b/kernel/src/arch/mipsel/board/thinpad/fb.rs @@ -0,0 +1,232 @@ +//! Framebuffer + +use super::mailbox; +use alloc::string::String; +use core::fmt; +use lazy_static::lazy_static; +use log::*; +use once::*; +use spin::Mutex; + +/// Framebuffer information +#[repr(C)] +#[derive(Debug, Clone, Copy)] +pub struct FramebufferInfo { + /// visible width + pub xres: u32, + /// visible height + pub yres: u32, + /// virtual width + pub xres_virtual: u32, + /// virtual height + pub yres_virtual: u32, + /// virtual offset x + pub xoffset: u32, + /// virtual offset y + pub yoffset: u32, + + /// bits per pixel + pub depth: u32, + /// bytes per line + pub pitch: u32, + + /// bus address, starts from 0xC0000000/0x40000000 + /// (see https://github.com/raspberrypi/firmware/wiki/Accessing-mailboxes) + pub bus_addr: u32, + /// screen buffer size + pub screen_size: u32, +} + +#[repr(u32)] +#[derive(Debug, Clone, Copy)] +pub enum ColorDepth { + ColorDepth16 = 16, + ColorDepth32 = 32, +} +use self::ColorDepth::*; + +#[repr(C)] +union ColorBuffer { + base_addr: usize, + buf16: &'static mut [u16], + buf32: &'static mut [u32], +} + +impl ColorBuffer { + fn new(color_depth: ColorDepth, base_addr: usize, size: usize) -> ColorBuffer { + unsafe { + match color_depth { + ColorDepth16 => ColorBuffer { + buf16: core::slice::from_raw_parts_mut(base_addr as *mut u16, size / 2), + }, + ColorDepth32 => ColorBuffer { + buf32: core::slice::from_raw_parts_mut(base_addr as *mut u32, size / 4), + }, + } + } + } + + #[inline] + fn read16(&self, index: u32) -> u16 { + unsafe { self.buf16[index as usize] } + } + + #[inline] + fn read32(&self, index: u32) -> u32 { + unsafe { self.buf32[index as usize] } + } + + #[inline] + fn write16(&mut self, index: u32, pixel: u16) { + unsafe { self.buf16[index as usize] = pixel } + } + + #[inline] + fn write32(&mut self, index: u32, pixel: u32) { + unsafe { self.buf32[index as usize] = pixel } + } +} + +/// Frambuffer structure +pub struct Framebuffer { + pub fb_info: FramebufferInfo, + pub color_depth: ColorDepth, + buf: ColorBuffer, +} + +impl fmt::Debug for Framebuffer { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + let mut f = f.debug_struct("Framebuffer"); + f.field("fb_info", &self.fb_info); + f.field("color_depth", &self.color_depth); + f.field("base_addr", unsafe { &self.buf.base_addr }); + f.finish() + } +} + +impl Framebuffer { + fn new(width: u32, height: u32, depth: u32) -> Result { + assert_has_not_been_called!("Framebuffer::new must be called only once"); + + let (width, height) = if width == 0 || height == 0 { + mailbox::framebuffer_get_physical_size()? + } else { + (width, height) + }; + let depth = if depth == 0 { + mailbox::framebuffer_get_depth()? + } else { + depth + }; + + let info = mailbox::framebuffer_alloc(width, height, depth)?; + let color_depth = match info.depth { + 16 => ColorDepth16, + 32 => ColorDepth32, + _ => Err(format!("unsupported color depth {}", info.depth))?, + }; + + if info.bus_addr == 0 || info.screen_size == 0 { + Err(format!("mailbox call returned an invalid address/size"))?; + } + if info.pitch == 0 || info.pitch != info.xres * info.depth / 8 { + Err(format!( + "mailbox call returned an invalid pitch value {}", + info.pitch + ))?; + } + + use crate::arch::memory; + let paddr = info.bus_addr & !0xC0000000; + let vaddr = memory::ioremap(paddr as usize, info.screen_size as usize, "fb"); + if vaddr == 0 { + Err(format!( + "cannot remap memory range [{:#x?}..{:#x?}]", + paddr, + paddr + info.screen_size + ))?; + } + Ok(Framebuffer { + buf: ColorBuffer::new(color_depth, vaddr, info.screen_size as usize), + color_depth, + fb_info: info, + }) + } + + #[inline] + pub fn base_addr(&self) -> usize { + unsafe { self.buf.base_addr } + } + + /// Read pixel at `(x, y)`. + #[inline] + pub fn read(&self, x: u32, y: u32) -> u32 { + match self.color_depth { + ColorDepth16 => self.buf.read16(y * self.fb_info.xres + x) as u32, + ColorDepth32 => self.buf.read32(y * self.fb_info.xres + x), + } + } + + /// Write pixel at `(x, y)`. + #[inline] + pub fn write(&mut self, x: u32, y: u32, pixel: u32) { + match self.color_depth { + ColorDepth16 => self.buf.write16(y * self.fb_info.xres + x, pixel as u16), + ColorDepth32 => self.buf.write32(y * self.fb_info.xres + x, pixel), + } + } + + /// Copy buffer `[src_off .. src_off + size]` to `[dst_off .. dst_off + size]`. + /// `dst_off`, `src_off` and `size` must be aligned with `usize`. + pub fn copy(&mut self, dst_off: usize, src_off: usize, size: usize) { + const USIZE: usize = core::mem::size_of::(); + let mut dst = self.base_addr() + dst_off; + let mut src = self.base_addr() + src_off; + let src_end = src + size; + while src < src_end { + unsafe { *(dst as *mut usize) = *(src as *mut usize) } + dst += USIZE; + src += USIZE; + } + } + + /// Fill buffer `[offset .. offset + size]` with `pixel`. + /// `offset` and `size` must be aligned with `usize`. + pub fn fill(&mut self, offset: usize, size: usize, pixel: u32) { + const USIZE: usize = core::mem::size_of::(); + let mut value: usize = 0; + let repeat = USIZE * 8 / self.fb_info.depth as usize; + let mask = ((1u64 << self.fb_info.depth) - 1) as usize; + for _i in 0..repeat { + value <<= self.fb_info.depth; + value += pixel as usize & mask; + } + + let mut start = self.base_addr() + offset; + let end = start + size; + while start < end { + unsafe { *(start as *mut usize) = value } + start += USIZE; + } + } + + /// Fill the entire buffer with `0`. + pub fn clear(&mut self) { + self.fill(0, self.fb_info.screen_size as usize, 0); + } +} + +lazy_static! { + pub static ref FRAME_BUFFER: Mutex> = Mutex::new(None); +} + +/// Initialize framebuffer +pub fn init() { + match Framebuffer::new(0, 0, 0) { + Ok(fb) => { + info!("framebuffer: init end\n{:#x?}", fb); + *FRAME_BUFFER.lock() = Some(fb); + } + Err(err) => warn!("framebuffer init failed: {}", err), + } +} diff --git a/kernel/src/arch/mipsel/board/thinpad/mod.rs b/kernel/src/arch/mipsel/board/thinpad/mod.rs index 1277ed7..dbfbb84 100644 --- a/kernel/src/arch/mipsel/board/thinpad/mod.rs +++ b/kernel/src/arch/mipsel/board/thinpad/mod.rs @@ -8,7 +8,7 @@ pub mod console; /// Initialize serial port first pub fn init_serial_early() { assert_has_not_been_called!("board::init must be called only once"); - serial::init(); + serial::init(0xa3000000); println!("Hello ThinPad!"); } @@ -16,5 +16,4 @@ pub fn init_serial_early() { pub fn init_driver() { // TODO: add possibly more drivers // timer::init(); - console::init(); } \ No newline at end of file diff --git a/kernel/src/arch/mipsel/board/thinpad/serial.rs b/kernel/src/arch/mipsel/board/thinpad/serial.rs new file mode 100644 index 0000000..3c59a0d --- /dev/null +++ b/kernel/src/arch/mipsel/board/thinpad/serial.rs @@ -0,0 +1,94 @@ +//! naive serial adapter driver for thinpad + +use core::fmt::{Write, Result, Arguments}; +use core::ptr::{read_volatile, write_volatile}; +use spin::Mutex; + +struct SerialPort { + base: usize +} + +const UART_STATUS: usize = 0; +const UART_DATA: usize = 0; + +const UART_STATUS_CTS: u8 = 0x1; // clear to send signal +const UART_STATUS_DR: u8 = 0x2; // data ready signal + + +impl SerialPort { + fn new() -> SerialPort { + SerialPort { + base: 0 + } + } + + pub fn init(&mut self, base: usize) { + self.base = base; + } + + /// non-blocking version of putchar() + fn putchar(&mut self, c: u8) { + write(self.base + UART_DATA, c); + } + + /// blocking version of getchar() + pub fn getchar(&mut self) -> char { + loop { + if (read::(self.base + UART_STATUS) & UART_STATUS_DR) == 0 { + break; + } + } + let c = read::(self.base + UART_DATA); + match c { + 255 => '\0', // null + c => c as char, + } + } + + /// non-blocking version of getchar() + pub fn getchar_option(&mut self) -> Option { + match read::(self.base + UART_STATUS) & UART_STATUS_DR { + 0 => None, + _ => Some(read::(self.base + UART_DATA) as u8 as char), + } + } + + pub fn putfmt(&mut self, fmt: Arguments) { + self.write_fmt(fmt).unwrap(); + } + +} + +impl Write for SerialPort { + fn write_str(&mut self, s: &str) -> Result { + for c in s.bytes() { + if c == 127 { + self.putchar(8); + self.putchar(b' '); + self.putchar(8); + } else { + self.putchar(c); + } + } + Ok(()) + } +} + +fn write(addr: usize, content: T) { + let cell = (addr) as *mut T; + write_volatile(cell, content); +} + +fn read(addr: usize) -> T { + let cell = (addr) as *const T; + read_volatile(cell); +} + + +lazy_static! { + pub static ref SERIAL_PORT: Mutex = Mutex::new(SerialPort::new()); +} + +pub fn init(base: usize) { + SERIAL_PORT.lock().init(base); +} From 8bc00324c8aaa2d631f45f543f9bb8ad8ac03bcb Mon Sep 17 00:00:00 2001 From: Harry Chen Date: Thu, 4 Apr 2019 00:10:18 +0800 Subject: [PATCH 21/85] Extract common framebuffer driver from aarch64 Signed-off-by: Harry Chen --- kernel/build.rs | 2 +- kernel/src/arch/aarch64/board/raspi3/mod.rs | 45 ++++ kernel/src/arch/mipsel/board/thinpad/fb.rs | 232 ------------------ kernel/src/arch/mipsel/board/thinpad/mod.rs | 17 ++ kernel/src/drivers/console/color.rs | 14 ++ kernel/src/drivers/console/mod.rs | 4 + .../board/raspi3 => drivers/gpu}/fb.rs | 78 +++--- 7 files changed, 117 insertions(+), 275 deletions(-) delete mode 100644 kernel/src/arch/mipsel/board/thinpad/fb.rs rename kernel/src/{arch/aarch64/board/raspi3 => drivers/gpu}/fb.rs (78%) diff --git a/kernel/build.rs b/kernel/build.rs index 3a0945f..3efcadb 100644 --- a/kernel/build.rs +++ b/kernel/build.rs @@ -53,7 +53,7 @@ fn gen_vector_asm() -> Result<()> { } -fn gen_dtb_asm(arch: &String, board: &String) -> Result<()> { +fn gen_dtb_asm(arch: &String, _board: &String) -> Result<()> { let dtb = std::env::var("DTB").unwrap(); if !Path::new(&dtb).is_file() { diff --git a/kernel/src/arch/aarch64/board/raspi3/mod.rs b/kernel/src/arch/aarch64/board/raspi3/mod.rs index 713c725..9b2a66b 100644 --- a/kernel/src/arch/aarch64/board/raspi3/mod.rs +++ b/kernel/src/arch/aarch64/board/raspi3/mod.rs @@ -2,13 +2,18 @@ use bcm2837::atags::Atags; use once::*; +use alloc::string::String; + +#[path = "../../../../drivers/gpu/fb.rs"] pub mod fb; pub mod irq; pub mod mailbox; pub mod serial; pub mod timer; +use fb::FramebufferInfo; + pub const IO_REMAP_BASE: usize = bcm2837::consts::IO_BASE; pub const IO_REMAP_END: usize = bcm2837::consts::KERNEL_OFFSET + 0x4000_1000; @@ -41,3 +46,43 @@ pub fn probe_memory() -> Option<(usize, usize)> { } None } + +pub fn probe_fb_info(width: u32, height: u32, depth: u32) -> Result<(FramebufferInfo, usize), String> { + + let (width, height) = if width == 0 || height == 0 { + mailbox::framebuffer_get_physical_size()? + } else { + (width, height) + }; + + let depth = if depth == 0 { + mailbox::framebuffer_get_depth()? + } else { + depth + }; + + let info = mailbox::framebuffer_alloc(width, height, depth)?; + + if info.bus_addr == 0 || info.screen_size == 0 { + Err(format!("mailbox call returned an invalid address/size"))?; + } + if info.pitch == 0 || info.pitch != info.xres * info.depth / 8 { + Err(format!( + "mailbox call returned an invalid pitch value {}", + info.pitch + ))?; + } + + use crate::arch::memory; + let paddr = info.bus_addr & !0xC0000000; + let vaddr = memory::ioremap(paddr as usize, info.screen_size as usize, "fb"); + if vaddr == 0 { + Err(format!( + "cannot remap memory range [{:#x?}..{:#x?}]", + paddr, + paddr + info.screen_size + ))?; + } + + Ok((info, vaddr)) +} \ No newline at end of file diff --git a/kernel/src/arch/mipsel/board/thinpad/fb.rs b/kernel/src/arch/mipsel/board/thinpad/fb.rs deleted file mode 100644 index ff3b31f..0000000 --- a/kernel/src/arch/mipsel/board/thinpad/fb.rs +++ /dev/null @@ -1,232 +0,0 @@ -//! Framebuffer - -use super::mailbox; -use alloc::string::String; -use core::fmt; -use lazy_static::lazy_static; -use log::*; -use once::*; -use spin::Mutex; - -/// Framebuffer information -#[repr(C)] -#[derive(Debug, Clone, Copy)] -pub struct FramebufferInfo { - /// visible width - pub xres: u32, - /// visible height - pub yres: u32, - /// virtual width - pub xres_virtual: u32, - /// virtual height - pub yres_virtual: u32, - /// virtual offset x - pub xoffset: u32, - /// virtual offset y - pub yoffset: u32, - - /// bits per pixel - pub depth: u32, - /// bytes per line - pub pitch: u32, - - /// bus address, starts from 0xC0000000/0x40000000 - /// (see https://github.com/raspberrypi/firmware/wiki/Accessing-mailboxes) - pub bus_addr: u32, - /// screen buffer size - pub screen_size: u32, -} - -#[repr(u32)] -#[derive(Debug, Clone, Copy)] -pub enum ColorDepth { - ColorDepth16 = 16, - ColorDepth32 = 32, -} -use self::ColorDepth::*; - -#[repr(C)] -union ColorBuffer { - base_addr: usize, - buf16: &'static mut [u16], - buf32: &'static mut [u32], -} - -impl ColorBuffer { - fn new(color_depth: ColorDepth, base_addr: usize, size: usize) -> ColorBuffer { - unsafe { - match color_depth { - ColorDepth16 => ColorBuffer { - buf16: core::slice::from_raw_parts_mut(base_addr as *mut u16, size / 2), - }, - ColorDepth32 => ColorBuffer { - buf32: core::slice::from_raw_parts_mut(base_addr as *mut u32, size / 4), - }, - } - } - } - - #[inline] - fn read16(&self, index: u32) -> u16 { - unsafe { self.buf16[index as usize] } - } - - #[inline] - fn read32(&self, index: u32) -> u32 { - unsafe { self.buf32[index as usize] } - } - - #[inline] - fn write16(&mut self, index: u32, pixel: u16) { - unsafe { self.buf16[index as usize] = pixel } - } - - #[inline] - fn write32(&mut self, index: u32, pixel: u32) { - unsafe { self.buf32[index as usize] = pixel } - } -} - -/// Frambuffer structure -pub struct Framebuffer { - pub fb_info: FramebufferInfo, - pub color_depth: ColorDepth, - buf: ColorBuffer, -} - -impl fmt::Debug for Framebuffer { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - let mut f = f.debug_struct("Framebuffer"); - f.field("fb_info", &self.fb_info); - f.field("color_depth", &self.color_depth); - f.field("base_addr", unsafe { &self.buf.base_addr }); - f.finish() - } -} - -impl Framebuffer { - fn new(width: u32, height: u32, depth: u32) -> Result { - assert_has_not_been_called!("Framebuffer::new must be called only once"); - - let (width, height) = if width == 0 || height == 0 { - mailbox::framebuffer_get_physical_size()? - } else { - (width, height) - }; - let depth = if depth == 0 { - mailbox::framebuffer_get_depth()? - } else { - depth - }; - - let info = mailbox::framebuffer_alloc(width, height, depth)?; - let color_depth = match info.depth { - 16 => ColorDepth16, - 32 => ColorDepth32, - _ => Err(format!("unsupported color depth {}", info.depth))?, - }; - - if info.bus_addr == 0 || info.screen_size == 0 { - Err(format!("mailbox call returned an invalid address/size"))?; - } - if info.pitch == 0 || info.pitch != info.xres * info.depth / 8 { - Err(format!( - "mailbox call returned an invalid pitch value {}", - info.pitch - ))?; - } - - use crate::arch::memory; - let paddr = info.bus_addr & !0xC0000000; - let vaddr = memory::ioremap(paddr as usize, info.screen_size as usize, "fb"); - if vaddr == 0 { - Err(format!( - "cannot remap memory range [{:#x?}..{:#x?}]", - paddr, - paddr + info.screen_size - ))?; - } - Ok(Framebuffer { - buf: ColorBuffer::new(color_depth, vaddr, info.screen_size as usize), - color_depth, - fb_info: info, - }) - } - - #[inline] - pub fn base_addr(&self) -> usize { - unsafe { self.buf.base_addr } - } - - /// Read pixel at `(x, y)`. - #[inline] - pub fn read(&self, x: u32, y: u32) -> u32 { - match self.color_depth { - ColorDepth16 => self.buf.read16(y * self.fb_info.xres + x) as u32, - ColorDepth32 => self.buf.read32(y * self.fb_info.xres + x), - } - } - - /// Write pixel at `(x, y)`. - #[inline] - pub fn write(&mut self, x: u32, y: u32, pixel: u32) { - match self.color_depth { - ColorDepth16 => self.buf.write16(y * self.fb_info.xres + x, pixel as u16), - ColorDepth32 => self.buf.write32(y * self.fb_info.xres + x, pixel), - } - } - - /// Copy buffer `[src_off .. src_off + size]` to `[dst_off .. dst_off + size]`. - /// `dst_off`, `src_off` and `size` must be aligned with `usize`. - pub fn copy(&mut self, dst_off: usize, src_off: usize, size: usize) { - const USIZE: usize = core::mem::size_of::(); - let mut dst = self.base_addr() + dst_off; - let mut src = self.base_addr() + src_off; - let src_end = src + size; - while src < src_end { - unsafe { *(dst as *mut usize) = *(src as *mut usize) } - dst += USIZE; - src += USIZE; - } - } - - /// Fill buffer `[offset .. offset + size]` with `pixel`. - /// `offset` and `size` must be aligned with `usize`. - pub fn fill(&mut self, offset: usize, size: usize, pixel: u32) { - const USIZE: usize = core::mem::size_of::(); - let mut value: usize = 0; - let repeat = USIZE * 8 / self.fb_info.depth as usize; - let mask = ((1u64 << self.fb_info.depth) - 1) as usize; - for _i in 0..repeat { - value <<= self.fb_info.depth; - value += pixel as usize & mask; - } - - let mut start = self.base_addr() + offset; - let end = start + size; - while start < end { - unsafe { *(start as *mut usize) = value } - start += USIZE; - } - } - - /// Fill the entire buffer with `0`. - pub fn clear(&mut self) { - self.fill(0, self.fb_info.screen_size as usize, 0); - } -} - -lazy_static! { - pub static ref FRAME_BUFFER: Mutex> = Mutex::new(None); -} - -/// Initialize framebuffer -pub fn init() { - match Framebuffer::new(0, 0, 0) { - Ok(fb) => { - info!("framebuffer: init end\n{:#x?}", fb); - *FRAME_BUFFER.lock() = Some(fb); - } - Err(err) => warn!("framebuffer init failed: {}", err), - } -} diff --git a/kernel/src/arch/mipsel/board/thinpad/mod.rs b/kernel/src/arch/mipsel/board/thinpad/mod.rs index dbfbb84..6c480f4 100644 --- a/kernel/src/arch/mipsel/board/thinpad/mod.rs +++ b/kernel/src/arch/mipsel/board/thinpad/mod.rs @@ -1,6 +1,7 @@ use once::*; pub mod serial; +#[path = "../../../../drivers/gpu/fb.rs"] pub mod fb; #[path = "../../../../drivers/console/mod.rs"] pub mod console; @@ -16,4 +17,20 @@ pub fn init_serial_early() { pub fn init_driver() { // TODO: add possibly more drivers // timer::init(); +} + +pub fn probe_fb_info(width: u32, height: u32, depth: u32) -> Result<(FramebufferInfo, u32), String> { + let fb_info = FramebufferInfo { + xres: 800, + yres: 600, + xres_virtual: 800, + yres_virtual: 600, + xoffset: 0, + yoffset: 0, + depth: 8, + pitch: 800, + bus_addr: 0xa2000000, + screen_size: 800 * 600, + } + Ok((fb_info, 0xa2000000)) } \ No newline at end of file diff --git a/kernel/src/drivers/console/color.rs b/kernel/src/drivers/console/color.rs index 419df50..1936fb8 100644 --- a/kernel/src/drivers/console/color.rs +++ b/kernel/src/drivers/console/color.rs @@ -3,6 +3,9 @@ use crate::util::color::ConsoleColor; pub trait FramebufferColor { + /// pack as 8-bit integer + fn pack8(&self) -> u8; + /// pack as 16-bit integer fn pack16(&self) -> u16; @@ -42,6 +45,12 @@ impl From for RgbColor { } impl FramebufferColor for RgbColor { + #[inline] + fn pack8(&self) -> u8 { + // RGB332 + ((self.0 >> 5) << 5) | ((self.1 >> 5) << 2) | (self.2 >> 6) + } + #[inline] fn pack16(&self) -> u16 { // BGR565 @@ -58,6 +67,11 @@ impl FramebufferColor for RgbColor { } impl FramebufferColor for ConsoleColor { + #[inline] + fn pack8(&self) -> u8 { + RgbColor::from(*self).pack8() + } + #[inline] fn pack16(&self) -> u16 { RgbColor::from(*self).pack16() diff --git a/kernel/src/drivers/console/mod.rs b/kernel/src/drivers/console/mod.rs index b16ae13..29d56be 100644 --- a/kernel/src/drivers/console/mod.rs +++ b/kernel/src/drivers/console/mod.rs @@ -63,6 +63,10 @@ impl ConsoleBuffer { let off_y = row * F::HEIGHT; if let Some(fb) = FRAME_BUFFER.lock().as_mut() { let (mut foreground, mut background) = match fb.color_depth { + ColorDepth8 => ( + ch.attr.foreground.pack8() as u32, + ch.attr.background.pack8() as u32, + ), ColorDepth16 => ( ch.attr.foreground.pack16() as u32, ch.attr.background.pack16() as u32, diff --git a/kernel/src/arch/aarch64/board/raspi3/fb.rs b/kernel/src/drivers/gpu/fb.rs similarity index 78% rename from kernel/src/arch/aarch64/board/raspi3/fb.rs rename to kernel/src/drivers/gpu/fb.rs index ff3b31f..d5f7021 100644 --- a/kernel/src/arch/aarch64/board/raspi3/fb.rs +++ b/kernel/src/drivers/gpu/fb.rs @@ -1,6 +1,5 @@ //! Framebuffer -use super::mailbox; use alloc::string::String; use core::fmt; use lazy_static::lazy_static; @@ -40,6 +39,7 @@ pub struct FramebufferInfo { #[repr(u32)] #[derive(Debug, Clone, Copy)] pub enum ColorDepth { + ColorDepth8 = 8, ColorDepth16 = 16, ColorDepth32 = 32, } @@ -48,6 +48,7 @@ use self::ColorDepth::*; #[repr(C)] union ColorBuffer { base_addr: usize, + buf8: &'static mut [u8], buf16: &'static mut [u16], buf32: &'static mut [u32], } @@ -56,6 +57,9 @@ impl ColorBuffer { fn new(color_depth: ColorDepth, base_addr: usize, size: usize) -> ColorBuffer { unsafe { match color_depth { + ColorDepth8 => ColorBuffer { + buf8: core::slice::from_raw_parts_mut(base_addr as *mut u8, size), + }, ColorDepth16 => ColorBuffer { buf16: core::slice::from_raw_parts_mut(base_addr as *mut u16, size / 2), }, @@ -66,6 +70,11 @@ impl ColorBuffer { } } + #[inline] + fn read8(&self, index: u32) -> u8 { + unsafe { self.buf8[index as usize] } + } + #[inline] fn read16(&self, index: u32) -> u16 { unsafe { self.buf16[index as usize] } @@ -76,6 +85,11 @@ impl ColorBuffer { unsafe { self.buf32[index as usize] } } + #[inline] + fn write8(&mut self, index: u32, pixel: u8) { + unsafe { self.buf8[index as usize] = pixel } + } + #[inline] fn write16(&mut self, index: u32, pixel: u16) { unsafe { self.buf16[index as usize] = pixel } @@ -108,49 +122,27 @@ impl Framebuffer { fn new(width: u32, height: u32, depth: u32) -> Result { assert_has_not_been_called!("Framebuffer::new must be called only once"); - let (width, height) = if width == 0 || height == 0 { - mailbox::framebuffer_get_physical_size()? - } else { - (width, height) - }; - let depth = if depth == 0 { - mailbox::framebuffer_get_depth()? - } else { - depth - }; - - let info = mailbox::framebuffer_alloc(width, height, depth)?; - let color_depth = match info.depth { - 16 => ColorDepth16, - 32 => ColorDepth32, - _ => Err(format!("unsupported color depth {}", info.depth))?, - }; - - if info.bus_addr == 0 || info.screen_size == 0 { - Err(format!("mailbox call returned an invalid address/size"))?; - } - if info.pitch == 0 || info.pitch != info.xres * info.depth / 8 { - Err(format!( - "mailbox call returned an invalid pitch value {}", - info.pitch - ))?; + let probed_info = super::probe_fb_info(width, height, depth); + + match probed_info { + Ok((info, addr)) => { + let color_depth = match info.depth { + 8 => ColorDepth8, + 16 => ColorDepth16, + 32 => ColorDepth32, + _ => Err(format!("unsupported color depth {}", info.depth))?, + }; + Ok(Framebuffer { + buf: ColorBuffer::new(color_depth, addr, info.screen_size as usize), + color_depth, + fb_info: info, + }) + }, + Err(e) => { + Err(e)? + }, } - use crate::arch::memory; - let paddr = info.bus_addr & !0xC0000000; - let vaddr = memory::ioremap(paddr as usize, info.screen_size as usize, "fb"); - if vaddr == 0 { - Err(format!( - "cannot remap memory range [{:#x?}..{:#x?}]", - paddr, - paddr + info.screen_size - ))?; - } - Ok(Framebuffer { - buf: ColorBuffer::new(color_depth, vaddr, info.screen_size as usize), - color_depth, - fb_info: info, - }) } #[inline] @@ -162,6 +154,7 @@ impl Framebuffer { #[inline] pub fn read(&self, x: u32, y: u32) -> u32 { match self.color_depth { + ColorDepth8 => self.buf.read8(y * self.fb_info.xres + x) as u32, ColorDepth16 => self.buf.read16(y * self.fb_info.xres + x) as u32, ColorDepth32 => self.buf.read32(y * self.fb_info.xres + x), } @@ -171,6 +164,7 @@ impl Framebuffer { #[inline] pub fn write(&mut self, x: u32, y: u32, pixel: u32) { match self.color_depth { + ColorDepth8 => self.buf.write8(y * self.fb_info.xres + x, pixel as u8), ColorDepth16 => self.buf.write16(y * self.fb_info.xres + x, pixel as u16), ColorDepth32 => self.buf.write32(y * self.fb_info.xres + x, pixel), } From 78b7c7b893b78f933d3c8fd784f4c715695bdd52 Mon Sep 17 00:00:00 2001 From: Harry Chen Date: Thu, 4 Apr 2019 21:55:59 +0800 Subject: [PATCH 22/85] Fix syscall handling for mipsel, update user programs repo Signed-off-by: Harry Chen --- kernel/src/arch/mipsel/interrupt.rs | 5 ++--- user | 2 +- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/kernel/src/arch/mipsel/interrupt.rs b/kernel/src/arch/mipsel/interrupt.rs index f78657a..909c7c1 100644 --- a/kernel/src/arch/mipsel/interrupt.rs +++ b/kernel/src/arch/mipsel/interrupt.rs @@ -115,10 +115,9 @@ fn timer() { } fn syscall(tf: &mut TrapFrame) { - // TODO tf.sepc += 4; // Must before syscall, because of fork. - let ret = crate::syscall::syscall(tf.x[17], [tf.x[10], tf.x[11], tf.x[12], tf.x[13], tf.x[14], tf.x[15]], tf); - tf.x[10] = ret as usize; + let ret = crate::syscall::syscall(tf.t0, [tf.x0, tf.x1, tf.x2, tf.x3, tf.s0, tf.s1], tf); + tf.v0 = ret as usize; } fn page_fault(tf: &mut TrapFrame) { diff --git a/user b/user index b1e7a2d..97bae0c 160000 --- a/user +++ b/user @@ -1 +1 @@ -Subproject commit b1e7a2d07e81ce5035a1cc25b0ade9367aee1a94 +Subproject commit 97bae0c39a7aeaab07654d99c3ba3bcb4d01658c From 05f9327272cd2dd74bbe810a30283f223cd2ec6e Mon Sep 17 00:00:00 2001 From: Yuhao Zhou Date: Fri, 5 Apr 2019 12:38:26 +0800 Subject: [PATCH 23/85] Update mips paging.rs. --- kernel/src/arch/mipsel/interrupt.rs | 4 +- kernel/src/arch/mipsel/mod.rs | 2 +- kernel/src/arch/mipsel/paging.rs | 158 ++++++---------------------- 3 files changed, 36 insertions(+), 128 deletions(-) diff --git a/kernel/src/arch/mipsel/interrupt.rs b/kernel/src/arch/mipsel/interrupt.rs index f6bea8a..2d356b0 100644 --- a/kernel/src/arch/mipsel/interrupt.rs +++ b/kernel/src/arch/mipsel/interrupt.rs @@ -1,5 +1,5 @@ -use mips::interrupts::*; -use mips::registers::*; +use mips::interrupts; +use mips::registers::cp0; use crate::drivers::DRIVERS; pub use self::context::*; use log::*; diff --git a/kernel/src/arch/mipsel/mod.rs b/kernel/src/arch/mipsel/mod.rs index bb3d87f..f2f5dd2 100644 --- a/kernel/src/arch/mipsel/mod.rs +++ b/kernel/src/arch/mipsel/mod.rs @@ -10,7 +10,7 @@ pub mod syscall; pub mod rand; use log::*; -use mips::registers; +use mips::registers::cp0; use mips::instructions; extern "C" { diff --git a/kernel/src/arch/mipsel/paging.rs b/kernel/src/arch/mipsel/paging.rs index a392865..79318ec 100644 --- a/kernel/src/arch/mipsel/paging.rs +++ b/kernel/src/arch/mipsel/paging.rs @@ -1,19 +1,15 @@ -use crate::consts::RECURSIVE_INDEX; // Depends on kernel use crate::memory::{active_table, alloc_frame, dealloc_frame}; -use riscv::addr::*; -use riscv::asm::{sfence_vma, sfence_vma_all}; -use riscv::paging::{Mapper, PageTable as RvPageTable, PageTableEntry, PageTableFlags as EF, RecursivePageTable, PageTableType}; -use riscv::paging::{FrameAllocator, FrameDeallocator}; -use riscv::register::satp; +use mips::addr::*; +use mips::tlb::*; +use mips::paging::{Mapper, PageTable as MIPSPageTable, PageTableEntry, PageTableFlags as EF, TwoLevelPageTable}; +use mips::paging::{FrameAllocator, FrameDeallocator}; use rcore_memory::paging::*; use log::*; #[cfg(target_arch = "riscv32")] use crate::consts::KERNEL_P2_INDEX; -#[cfg(target_arch = "riscv64")] -use crate::consts::KERNEL_P4_INDEX; -pub struct ActivePageTable(RecursivePageTable<'static>, PageEntry); +pub struct ActivePageTable(TwoLevelPageTable<'static>, PageEntry); /// PageTableEntry: the contents of this entry. /// Page: this entry is the pte of page `Page`. @@ -22,9 +18,8 @@ pub struct PageEntry(&'static mut PageTableEntry, Page); impl PageTable for ActivePageTable { fn map(&mut self, addr: usize, target: usize) -> &mut Entry { - // use riscv::paging:Mapper::map_to, // map the 4K `page` to the 4K `frame` with `flags` - let flags = EF::VALID | EF::READABLE | EF::WRITABLE; + let flags = EF::VALID | EF::WRITABLE | EF::CACHEABLE; let page = Page::of_addr(VirtAddr::new(addr)); let frame = Frame::of_addr(PhysAddr::new(target)); // map the page to the frame using FrameAllocatorForRiscv @@ -54,41 +49,14 @@ impl PageTable for ActivePageTable { impl PageTableExt for ActivePageTable {} /// The virtual address of root page table -#[cfg(target_arch = "riscv32")] -const ROOT_PAGE_TABLE: *mut RvPageTable = - ((RECURSIVE_INDEX << 12 << 10) | - ((RECURSIVE_INDEX+1) << 12)) as *mut RvPageTable; -#[cfg(all(target_arch = "riscv64", feature = "sv39"))] -const ROOT_PAGE_TABLE: *mut RvPageTable = - ((0xFFFF_0000_0000_0000) | - (0o777 << 12 << 9 << 9 << 9) | - (RECURSIVE_INDEX << 12 << 9 << 9) | - (RECURSIVE_INDEX << 12 << 9) | - ((RECURSIVE_INDEX+1) << 12)) as *mut RvPageTable; -#[cfg(all(target_arch = "riscv64", not(feature = "sv39")))] -const ROOT_PAGE_TABLE: *mut RvPageTable = - ((0xFFFF_0000_0000_0000) | - (RECURSIVE_INDEX << 12 << 9 << 9 << 9) | - (RECURSIVE_INDEX << 12 << 9 << 9) | - (RECURSIVE_INDEX << 12 << 9) | - ((RECURSIVE_INDEX+1) << 12)) as *mut RvPageTable; +static ROOT_PAGE_TABLE_BUFFER: MIPSPageTable = ::core::mem::uninitialized(); +static mut root_page_table_ptr: usize = + &ROOT_PAGE_TABLE_BUFFER as *const MIPSPageTable as usize; impl ActivePageTable { - #[cfg(target_arch = "riscv32")] - pub unsafe fn new() -> Self { - ActivePageTable( - RecursivePageTable::new(&mut *ROOT_PAGE_TABLE).unwrap(), - ::core::mem::uninitialized() - ) - } - #[cfg(target_arch = "riscv64")] pub unsafe fn new() -> Self { - #[cfg(feature = "sv39")] - let type_ = PageTableType::Sv39; - #[cfg(not(feature = "sv39"))] - let type_ = PageTableType::Sv48; ActivePageTable( - RecursivePageTable::new(&mut *ROOT_PAGE_TABLE, type_).unwrap(), + TwoLevelPageTable::new(&mut ROOT_PAGE_TABLE_BUFFER), ::core::mem::uninitialized() ) } @@ -97,36 +65,32 @@ impl ActivePageTable { /// implementation for the Entry trait in /crate/memory/src/paging/mod.rs impl Entry for PageEntry { fn update(&mut self) { - unsafe { sfence_vma(0, self.1.start_address().as_usize()); } + unsafe { clear_all_tlb(); } } fn accessed(&self) -> bool { self.0.flags().contains(EF::ACCESSED) } fn dirty(&self) -> bool { self.0.flags().contains(EF::DIRTY) } fn writable(&self) -> bool { self.0.flags().contains(EF::WRITABLE) } - fn present(&self) -> bool { self.0.flags().contains(EF::VALID | EF::READABLE) } + fn present(&self) -> bool { self.0.flags().contains(EF::VALID) } fn clear_accessed(&mut self) { self.0.flags_mut().remove(EF::ACCESSED); } fn clear_dirty(&mut self) { self.0.flags_mut().remove(EF::DIRTY); } fn set_writable(&mut self, value: bool) { self.0.flags_mut().set(EF::WRITABLE, value); } - fn set_present(&mut self, value: bool) { self.0.flags_mut().set(EF::VALID | EF::READABLE, value); } + fn set_present(&mut self, value: bool) { self.0.flags_mut().set(EF::VALID, value); } fn target(&self) -> usize { self.0.addr().as_usize() } fn set_target(&mut self, target: usize) { let flags = self.0.flags(); let frame = Frame::of_addr(PhysAddr::new(target)); self.0.set(frame, flags); } - fn writable_shared(&self) -> bool { self.0.flags().contains(EF::RESERVED1) } - fn readonly_shared(&self) -> bool { self.0.flags().contains(EF::RESERVED2) } - fn set_shared(&mut self, writable: bool) { - let flags = self.0.flags_mut(); - flags.set(EF::RESERVED1, writable); - flags.set(EF::RESERVED2, !writable); - } - fn clear_shared(&mut self) { self.0.flags_mut().remove(EF::RESERVED1 | EF::RESERVED2); } + fn writable_shared(&self) -> bool { false } + fn readonly_shared(&self) -> bool { false } + fn set_shared(&mut self, writable: bool) { } + fn clear_shared(&mut self) { } fn swapped(&self) -> bool { self.0.flags().contains(EF::RESERVED1) } fn set_swapped(&mut self, value: bool) { self.0.flags_mut().set(EF::RESERVED1, value); } - fn user(&self) -> bool { self.0.flags().contains(EF::USER) } - fn set_user(&mut self, value: bool) { self.0.flags_mut().set(EF::USER, value); } - fn execute(&self) -> bool { self.0.flags().contains(EF::EXECUTABLE) } - fn set_execute(&mut self, value: bool) { self.0.flags_mut().set(EF::EXECUTABLE, value); } + fn user(&self) -> bool { true } + fn set_user(&mut self, value: bool) { } + fn execute(&self) -> bool { true } + fn set_execute(&mut self, value: bool) { } fn mmio(&self) -> u8 { 0 } fn set_mmio(&mut self, _value: u8) { } } @@ -142,93 +106,37 @@ impl InactivePageTable for InactivePageTable0 { fn new_bare() -> Self { let target = alloc_frame().expect("failed to allocate frame"); let frame = Frame::of_addr(PhysAddr::new(target)); - active_table().with_temporary_map(target, |_, table: &mut RvPageTable| { + active_table().with_temporary_map(target, |_, table: &mut MIPSPageTable| { table.zero(); - table.set_recursive(RECURSIVE_INDEX, frame.clone()); }); InactivePageTable0 { root_frame: frame } } - #[cfg(target_arch = "riscv32")] - fn map_kernel(&mut self) { - let table = unsafe { &mut *ROOT_PAGE_TABLE }; - extern { - fn start(); - fn end(); - } - let mut entrys: [PageTableEntry; 16] = unsafe { core::mem::uninitialized() }; - let entry_start = start as usize >> 22; - let entry_end = (end as usize >> 22) + 1; - let entry_count = entry_end - entry_start; - for i in 0..entry_count { - entrys[i] = table[entry_start + i]; - } - - self.edit(|_| { - // NOTE: 'table' now refers to new page table - for i in 0..entry_count { - table[entry_start + i] = entrys[i]; - } - }); - } - - #[cfg(target_arch = "riscv64")] - fn map_kernel(&mut self) { - let table = unsafe { &mut *ROOT_PAGE_TABLE }; - let e1 = table[KERNEL_P4_INDEX]; - assert!(!e1.is_unused()); - - self.edit(|_| { - table[KERNEL_P4_INDEX] = e1; - }); - } + fn map_kernel(&mut self) { /* nothing to do */ } - #[cfg(target_arch = "riscv32")] fn token(&self) -> usize { - self.root_frame.number() | (1 << 31) // as satp - } - #[cfg(target_arch = "riscv64")] - fn token(&self) -> usize { - use bit_field::BitField; - let mut satp = self.root_frame.number(); - satp.set_bits(44..60, 0); // AS is 0 - #[cfg(feature = "sv39")] - satp.set_bits(60..64, satp::Mode::Sv39 as usize); - #[cfg(not(feature = "sv39"))] - satp.set_bits(60..64, satp::Mode::Sv48 as usize); - satp + self.root_frame.to_kernel_unmapped().as_usize() } unsafe fn set_token(token: usize) { - asm!("csrw satp, $0" :: "r"(token) :: "volatile"); + root_page_table_ptr = token; } fn active_token() -> usize { - satp::read().bits() + root_page_table_ptr } fn flush_tlb() { - unsafe { sfence_vma_all(); } + unsafe { clear_all_tlb(); } } fn edit(&mut self, f: impl FnOnce(&mut Self::Active) -> T) -> T { - let target = satp::read().frame().start_address().as_usize(); - active_table().with_temporary_map(target, |active_table, root_table: &mut RvPageTable| { - let backup = root_table[RECURSIVE_INDEX].clone(); - - // overwrite recursive mapping - root_table[RECURSIVE_INDEX].set(self.root_frame.clone(), EF::VALID); - unsafe { sfence_vma_all(); } - - // execute f in the new context - let ret = f(active_table); - - // restore recursive mapping to original p2 table - root_table[RECURSIVE_INDEX] = backup; - unsafe { sfence_vma_all(); } - - ret - }) + let pt: *MIPSPageTable = self.token() as *MIPSPageTable; + let active = ActivePageTable( + TwoLevelPageTable::new(&mut *pt), + ::core::mem::uninitialized() + ); + f(&mut active) } } From 1fba79d26aa6cedf92c2d6a34f265af5fa6e6271 Mon Sep 17 00:00:00 2001 From: Yuhao Zhou Date: Fri, 5 Apr 2019 12:47:29 +0800 Subject: [PATCH 24/85] Fix a syntax error. --- kernel/src/arch/mipsel/paging.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/src/arch/mipsel/paging.rs b/kernel/src/arch/mipsel/paging.rs index 79318ec..2eb7513 100644 --- a/kernel/src/arch/mipsel/paging.rs +++ b/kernel/src/arch/mipsel/paging.rs @@ -131,7 +131,7 @@ impl InactivePageTable for InactivePageTable0 { } fn edit(&mut self, f: impl FnOnce(&mut Self::Active) -> T) -> T { - let pt: *MIPSPageTable = self.token() as *MIPSPageTable; + let pt: *mut MIPSPageTable = self.token() as *mut MIPSPageTable; let active = ActivePageTable( TwoLevelPageTable::new(&mut *pt), ::core::mem::uninitialized() From 53317e84c4b65b024fabbcaf712ab70fa6d3b4a5 Mon Sep 17 00:00:00 2001 From: Yuhao Zhou Date: Fri, 5 Apr 2019 21:02:39 +0800 Subject: [PATCH 25/85] Add context. --- kernel/src/arch/mipsel/context.rs | 166 ++++++++++++---------------- kernel/src/arch/mipsel/interrupt.rs | 4 +- kernel/src/arch/mipsel/paging.rs | 2 +- 3 files changed, 76 insertions(+), 96 deletions(-) diff --git a/kernel/src/arch/mipsel/context.rs b/kernel/src/arch/mipsel/context.rs index 8c4a996..09514c4 100644 --- a/kernel/src/arch/mipsel/context.rs +++ b/kernel/src/arch/mipsel/context.rs @@ -1,52 +1,53 @@ -use mips::registers; +use mips::registers::cp0; +use crate::arch::paging::root_page_table_ptr; /// Saved registers on a trap. #[derive(Clone)] #[repr(C)] pub struct TrapFrame { /// CP0 status register - pub status: u32, + pub status: cp0::status::Status, /// CP0 cause register - pub cause: u32, + pub cause: cp0::cause::Cause, /// CP0 EPC register - pub epc: u32, + pub epc: usize, /// CP0 vaddr register - pub vaddr: u32, + pub vaddr: usize, /// HI/LO registers - pub hi: u32, - pub lo: u32, + pub hi: usize, + pub lo: usize, /// General registers - pub at: u32, - pub v0: u32, - pub v1: u32, - pub a0: u32, - pub a1: u32, - pub a2: u32, - pub a3: u32, - pub t0: u32, - pub t1: u32, - pub t2: u32, - pub t3: u32, - pub t4: u32, - pub t5: u32, - pub t6: u32, - pub t7: u32, - pub s0: u32, - pub s1: u32, - pub s2: u32, - pub s3: u32, - pub s4: u32, - pub s5: u32, - pub s6: u32, - pub s7: u32, - pub t8: u32, - pub t9: u32, - pub k0: u32, - pub k1: u32, - pub gp: u32, - pub sp: u32, - pub fp: u32, - pub ra: u32, + pub at: usize, + pub v0: usize, + pub v1: usize, + pub a0: usize, + pub a1: usize, + pub a2: usize, + pub a3: usize, + pub t0: usize, + pub t1: usize, + pub t2: usize, + pub t3: usize, + pub t4: usize, + pub t5: usize, + pub t6: usize, + pub t7: usize, + pub s0: usize, + pub s1: usize, + pub s2: usize, + pub s3: usize, + pub s4: usize, + pub s5: usize, + pub s6: usize, + pub s7: usize, + pub t8: usize, + pub t9: usize, + pub k0: usize, + pub k1: usize, + pub gp: usize, + pub sp: usize, + pub fp: usize, + pub ra: usize, /// Reserve space for hartid pub _hartid: usize, } @@ -59,13 +60,13 @@ impl TrapFrame { fn new_kernel_thread(entry: extern fn(usize) -> !, arg: usize, sp: usize) -> Self { use core::mem::zeroed; let mut tf: Self = unsafe { zeroed() }; - tf.x[10] = arg; // a0 - tf.x[2] = sp; - tf.sepc = entry as usize; - tf.sstatus = sstatus::read(); - tf.sstatus.set_spie(true); - tf.sstatus.set_sie(false); - tf.sstatus.set_spp(sstatus::SPP::Supervisor); + tf.a0 = arg; + tf.sp = sp; + tf.epc = entry as usize; + tf.status = cp0::status::read(); + tf.status.set_kernel_mode(); + tf.status.set_ie(); + tf.status.set_exl(); tf } @@ -76,12 +77,12 @@ impl TrapFrame { fn new_user_thread(entry_addr: usize, sp: usize) -> Self { use core::mem::zeroed; let mut tf: Self = unsafe { zeroed() }; - tf.x[2] = sp; - tf.sepc = entry_addr; - tf.sstatus = sstatus::read(); - tf.sstatus.set_spie(true); - tf.sstatus.set_sie(false); - tf.sstatus.set_spp(sstatus::SPP::User); + tf.sp = sp; + tf.epc = entry_addr; + tf.status = cp0::status::read(); + tf.status.set_user_mode(); + tf.status.set_ie(); + tf.status.set_exl(); tf } } @@ -89,23 +90,11 @@ impl TrapFrame { use core::fmt::{Debug, Formatter, Error}; impl Debug for TrapFrame { fn fmt(&self, f: &mut Formatter) -> Result<(), Error> { - struct Regs<'a>(&'a [usize; 32]); - impl<'a> Debug for Regs<'a> { - fn fmt(&self, f: &mut Formatter) -> Result<(), Error> { - const REG_NAME: [&str; 32] = [ - "zero", "ra", "sp", "gp", "tp", "t0", "t1", "t2", - "s0", "s1", "a0", "a1", "a2", "a3", "a4", "a5", "a6", "a7", - "s2", "s3", "s4", "s5", "s6", "s7", "s8", "s9", "s10", "s11", - "t3", "t4", "t5", "t6"]; - f.debug_map().entries(REG_NAME.iter().zip(self.0)).finish() - } - } f.debug_struct("TrapFrame") - .field("regs", &Regs(&self.x)) - .field("sstatus", &self.sstatus) - .field("sepc", &self.sepc) - .field("stval", &self.stval) - .field("scause", &self.scause.cause()) + .field("status", &self.status.bits) + .field("epc", &self.epc.bits) + .field("cause", &self.cause.bits) + .field("vaddr", &self.vaddr.bits) .finish() } } @@ -167,7 +156,6 @@ impl Context { #[naked] #[inline(never)] pub unsafe extern fn switch(&mut self, _target: &mut Self) { - #[cfg(target_arch = "riscv32")] asm!(r" .equ XLENB, 4 .macro Load reg, mem @@ -176,15 +164,6 @@ impl Context { .macro Store reg, mem sw \reg, \mem .endm"); - #[cfg(target_arch = "riscv64")] - asm!(r" - .equ XLENB, 8 - .macro Load reg, mem - ld \reg, \mem - .endm - .macro Store reg, mem - sd \reg, \mem - .endm"); asm!(" // save from's registers addi sp, sp, (-XLENB*14) @@ -199,16 +178,16 @@ impl Context { Store s6, 8*XLENB(sp) Store s7, 9*XLENB(sp) Store s8, 10*XLENB(sp) - Store s9, 11*XLENB(sp) - Store s10, 12*XLENB(sp) - Store s11, 13*XLENB(sp) - csrr s11, satp - Store s11, 1*XLENB(sp) + Store gp, 11*XLENB(sp) + Store ra, 12*XLENB(sp) + Store sp, 13*XLENB(sp) + + Store $1, 1*XLENB(sp) // restore to's registers Load sp, 0(a1) - Load s11, 1*XLENB(sp) - csrw satp, s11 + Load $0, 1*XLENB(sp) + Load ra, 0*XLENB(sp) Load s0, 2*XLENB(sp) Load s1, 3*XLENB(sp) @@ -219,14 +198,15 @@ impl Context { Load s6, 8*XLENB(sp) Load s7, 9*XLENB(sp) Load s8, 10*XLENB(sp) - Load s9, 11*XLENB(sp) - Load s10, 12*XLENB(sp) - Load s11, 13*XLENB(sp) + Load gp, 11*XLENB(sp) + Load ra, 12*XLENB(sp) + Load sp, 13*XLENB(sp) addi sp, sp, (XLENB*14) Store zero, 0(a1) - ret" - : : : : "volatile" ) + jr ra + nop" + :"=r"(root_page_table_ptr) :"r"(root_page_table_ptr) : : "volatile" ) } /// Constructs a null Context for the current running thread. @@ -269,7 +249,7 @@ impl Context { tf: { let mut tf = tf.clone(); // fork function's ret value, the new process is 0 - tf.x[10] = 0; // a0 + tf.a0 = 0; tf }, }.push_at(kstack_top) @@ -287,9 +267,9 @@ impl Context { context: ContextData::new(satp), tf: { let mut tf = tf.clone(); - tf.x[2] = ustack_top; // sp - tf.x[4] = tls; // tp - tf.x[10] = 0; // a0 + tf.sp = ustack_top; // sp + tf.v1 = tls; // tp + tf.a0 = 0; // a0 tf }, }.push_at(kstack_top) diff --git a/kernel/src/arch/mipsel/interrupt.rs b/kernel/src/arch/mipsel/interrupt.rs index 909c7c1..12fda2e 100644 --- a/kernel/src/arch/mipsel/interrupt.rs +++ b/kernel/src/arch/mipsel/interrupt.rs @@ -40,7 +40,7 @@ pub unsafe fn enable() { pub unsafe fn disable_and_store() -> usize { let e = cp0::status::read_u32() & 1; interrupts::disable(); - e + e as usize } /// Enable interrupt if `flags` != 0 @@ -116,7 +116,7 @@ fn timer() { fn syscall(tf: &mut TrapFrame) { tf.sepc += 4; // Must before syscall, because of fork. - let ret = crate::syscall::syscall(tf.t0, [tf.x0, tf.x1, tf.x2, tf.x3, tf.s0, tf.s1], tf); + let ret = crate::syscall::syscall(tf.t0, [tf.t0, tf.t1, tf.t2, tf.t3, tf.s0, tf.s1], tf); tf.v0 = ret as usize; } diff --git a/kernel/src/arch/mipsel/paging.rs b/kernel/src/arch/mipsel/paging.rs index 2eb7513..3cc63c3 100644 --- a/kernel/src/arch/mipsel/paging.rs +++ b/kernel/src/arch/mipsel/paging.rs @@ -50,7 +50,7 @@ impl PageTableExt for ActivePageTable {} /// The virtual address of root page table static ROOT_PAGE_TABLE_BUFFER: MIPSPageTable = ::core::mem::uninitialized(); -static mut root_page_table_ptr: usize = +pub static mut root_page_table_ptr: usize = &ROOT_PAGE_TABLE_BUFFER as *const MIPSPageTable as usize; impl ActivePageTable { From a10a7cafa10eb873680b30f7fb201ae4ac131c2b Mon Sep 17 00:00:00 2001 From: Yuhao Zhou Date: Fri, 5 Apr 2019 21:18:24 +0800 Subject: [PATCH 26/85] Add interrupt dispatcher. --- kernel/src/arch/mipsel/context.rs | 4 +- kernel/src/arch/mipsel/cpu.rs | 18 ++----- kernel/src/arch/mipsel/interrupt.rs | 73 ++++++++++++++++------------- 3 files changed, 47 insertions(+), 48 deletions(-) diff --git a/kernel/src/arch/mipsel/context.rs b/kernel/src/arch/mipsel/context.rs index 09514c4..c968874 100644 --- a/kernel/src/arch/mipsel/context.rs +++ b/kernel/src/arch/mipsel/context.rs @@ -92,9 +92,9 @@ impl Debug for TrapFrame { fn fmt(&self, f: &mut Formatter) -> Result<(), Error> { f.debug_struct("TrapFrame") .field("status", &self.status.bits) - .field("epc", &self.epc.bits) + .field("epc", &self.epc) .field("cause", &self.cause.bits) - .field("vaddr", &self.vaddr.bits) + .field("vaddr", &self.vaddr) .finish() } } diff --git a/kernel/src/arch/mipsel/cpu.rs b/kernel/src/arch/mipsel/cpu.rs index dea1df9..ea27d1f 100644 --- a/kernel/src/arch/mipsel/cpu.rs +++ b/kernel/src/arch/mipsel/cpu.rs @@ -1,20 +1,11 @@ +use mips::registers::cp0; use crate::consts::MAX_CPU_NUM; use core::ptr::{read_volatile, write_volatile}; static mut STARTED: [bool; MAX_CPU_NUM] = [false; MAX_CPU_NUM]; -pub unsafe fn set_cpu_id(cpu_id: usize) { - asm!("mv gp, $0" : : "r"(cpu_id)); -} - pub fn id() -> usize { - let cpu_id; - unsafe { asm!("mv $0, gp" : "=r"(cpu_id)); } - cpu_id -} - -pub fn send_ipi(cpu_id: usize) { - super::sbi::send_ipi(1 << cpu_id); + (cp0::ebase::read_u32() as usize) & 0x3ff } pub unsafe fn has_started(cpu_id: usize) -> bool { @@ -30,9 +21,10 @@ pub unsafe fn start_others(hart_mask: usize) { } pub fn halt() { - unsafe { riscv::asm::wfi() } + /* nothing to do */ } pub unsafe fn exit_in_qemu(error_code: u8) -> ! { - super::sbi::shutdown() + /* nothing to do */ + loop {} } diff --git a/kernel/src/arch/mipsel/interrupt.rs b/kernel/src/arch/mipsel/interrupt.rs index 12fda2e..22f23ce 100644 --- a/kernel/src/arch/mipsel/interrupt.rs +++ b/kernel/src/arch/mipsel/interrupt.rs @@ -9,24 +9,23 @@ mod context; /// Initialize interrupt pub fn init() { - // TODO - // extern { - // fn trap_entry(); - // } - // unsafe { - // // Set sscratch register to 0, indicating to exception vector that we are - // // presently executing in the kernel - // sscratch::write(0); - // // Set the exception vector address - // stvec::write(trap_entry as usize, stvec::TrapMode::Direct); - // // Enable IPI - // sie::set_ssoft(); - // // Enable external interrupt - // if super::cpu::id() == super::BOOT_HART_ID { - // sie::set_sext(); - // } - // } - // info!("interrupt: init end"); + extern { + fn trap_entry(); + } + unsafe { + // Set the exception vector address + cp0::ebase::write_u32(trap_entry as u32); + + let mut status = cp0::status::read(); + // Enable IPI + status.enable_soft_int0(); + status.enable_soft_int1(); + // Enable clock interrupt + status.enable_hard_int5(); + + cp0::status::write(status); + } + info!("interrupt: init end"); } /// Enable interrupt @@ -56,22 +55,30 @@ pub unsafe fn restore(flags: usize) { /// This function is called from `trap.asm`. #[no_mangle] pub extern fn rust_trap(tf: &mut TrapFrame) { - // TODO - use self::scause::{Trap, Interrupt as I, Exception as E}; - // trace!("Interrupt @ CPU{}: {:?} ", super::cpu::id(), tf.scause.cause()); - match tf.scause.cause() { - Trap::Interrupt(I::SupervisorExternal) => external(), - Trap::Interrupt(I::SupervisorSoft) => ipi(), - Trap::Interrupt(I::SupervisorTimer) => timer(), - Trap::Exception(E::UserEnvCall) => syscall(tf), - Trap::Exception(E::LoadPageFault) => page_fault(tf), - Trap::Exception(E::StorePageFault) => page_fault(tf), - Trap::Exception(E::InstructionPageFault) => page_fault(tf), + use cp0::cause::{Exception as E}; + trace!("Interrupt @ CPU{}: {:?} ", 0, tf.cause.cause()); + match tf.cause.cause() { + E::Interrupt => interrupt_dispatcher(), + E::Syscall => syscall(tf), + E::TLBModification => page_fault(tf), + E::TLBLoadMiss => page_fault(tf), + E::TLBStoreMiss => page_fault(tf), _ => crate::trap::error(tf), } trace!("Interrupt end"); } +fn interrupt_dispatcher(tf: &mut TrapFrame) { + let pint = tf.cause.pending_interrupt(); + if (pint & 0b10000_00) != 0 { + timer(); + } else if (pint & 0xb01111_00) != 0 { + external(); + } else { + ipi(); + } +} + fn external() { // TODO // true means handled, false otherwise @@ -104,7 +111,7 @@ fn try_process_drivers() -> bool { } fn ipi() { - // TODO + /* do nothing */ debug!("IPI"); // super::sbi::clear_ipi(); } @@ -115,14 +122,14 @@ fn timer() { } fn syscall(tf: &mut TrapFrame) { - tf.sepc += 4; // Must before syscall, because of fork. + tf.epc += 4; // Must before syscall, because of fork. let ret = crate::syscall::syscall(tf.t0, [tf.t0, tf.t1, tf.t2, tf.t3, tf.s0, tf.s1], tf); tf.v0 = ret as usize; } fn page_fault(tf: &mut TrapFrame) { - // TODO - let addr = tf.stval; + // TODO: set access/dirty bit + let addr = tf.vaddr; trace!("\nEXCEPTION: Page Fault @ {:#x}", addr); if !crate::memory::handle_page_fault(addr) { From e8071b5d50f46ccdeeb0ce1ae7a704ef800fa97f Mon Sep 17 00:00:00 2001 From: Yuhao Zhou Date: Fri, 5 Apr 2019 21:22:21 +0800 Subject: [PATCH 27/85] Fix a minor bug. --- kernel/src/arch/mipsel/interrupt.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/src/arch/mipsel/interrupt.rs b/kernel/src/arch/mipsel/interrupt.rs index 22f23ce..c87f223 100644 --- a/kernel/src/arch/mipsel/interrupt.rs +++ b/kernel/src/arch/mipsel/interrupt.rs @@ -58,7 +58,7 @@ pub extern fn rust_trap(tf: &mut TrapFrame) { use cp0::cause::{Exception as E}; trace!("Interrupt @ CPU{}: {:?} ", 0, tf.cause.cause()); match tf.cause.cause() { - E::Interrupt => interrupt_dispatcher(), + E::Interrupt => interrupt_dispatcher(tf), E::Syscall => syscall(tf), E::TLBModification => page_fault(tf), E::TLBLoadMiss => page_fault(tf), From 9f7f82a72d21b10af915546f9d83e81a2261b7dc Mon Sep 17 00:00:00 2001 From: Harry Chen Date: Fri, 5 Apr 2019 22:57:12 +0800 Subject: [PATCH 28/85] Fix compilation errors in drivers Signed-off-by: Harry Chen --- kernel/Cargo.lock | 10 +++++++--- kernel/Cargo.toml | 6 +++--- kernel/src/arch/mipsel/board/malta/fb.rs | 13 ------------- kernel/src/arch/mipsel/board/malta/mod.rs | 6 ++++++ kernel/src/arch/mipsel/board/malta/serial.rs | 4 ++-- kernel/src/arch/mipsel/board/thinpad/mod.rs | 2 +- kernel/src/arch/mipsel/mod.rs | 2 +- 7 files changed, 20 insertions(+), 23 deletions(-) delete mode 100644 kernel/src/arch/mipsel/board/malta/fb.rs diff --git a/kernel/Cargo.lock b/kernel/Cargo.lock index 942a0a9..15929e7 100644 --- a/kernel/Cargo.lock +++ b/kernel/Cargo.lock @@ -230,7 +230,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "mips" version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" +source = "git+https://github.com/Harry-Chen/rust-mips#8b8cbacb08aaaef93837d46599ce21759ef481de" +dependencies = [ + "bit_field 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", +] [[package]] name = "nodrop" @@ -322,7 +326,7 @@ dependencies = [ "isomorphic_drivers 0.1.0 (git+https://github.com/rcore-os/isomorphic_drivers)", "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "mips 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "mips 0.1.0 (git+https://github.com/Harry-Chen/rust-mips)", "once 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "pc-keyboard 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", "pci 0.0.1 (git+https://github.com/rcore-os/pci-rs)", @@ -622,7 +626,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "e19e8d5c34a3e0e2223db8e060f9e8264aeeb5c5fc64a4ee9965c062211c024b" "checksum log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c84ec4b527950aa83a329754b01dbe3f58361d1c5efacd1f6d68c494d08a17c6" "checksum managed 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "fdcec5e97041c7f0f1c5b7d93f12e57293c831c646f4cc7a5db59460c7ea8de6" -"checksum mips 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f79c54c0ff7e933ffe5b3ec7c3c05037b654c334b0c98e66536d2d8906435394" +"checksum mips 0.1.0 (git+https://github.com/Harry-Chen/rust-mips)" = "" "checksum nodrop 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "2f9667ddcc6cc8a43afc9b7917599d7216aa09c463919ea32c59ed6cac8bc945" "checksum once 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "931fb7a4cf34610cf6cbe58d52a8ca5ef4c726d4e2e178abd0dc13a6551c6d73" "checksum os_bootinfo 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "66481dbeb5e773e7bd85b63cd6042c30786f834338288c5ec4f3742673db360a" diff --git a/kernel/Cargo.toml b/kernel/Cargo.toml index 4e7758c..2ce9880 100644 --- a/kernel/Cargo.toml +++ b/kernel/Cargo.toml @@ -27,9 +27,9 @@ nographic = [] board_raspi3 = ["bcm2837", "link_user"] raspi3_use_generic_timer = ["bcm2837/use_generic_timer"] # for mipsel qemu malta machine -board_malta = [] +board_malta = ["link_user"] # for thinpad -board_thinpad = [] +board_thinpad = ["link_user"] # Hard link user program link_user = [] # Run cmdline instead of user shell, useful for automatic testing @@ -77,7 +77,7 @@ aarch64 = { git = "https://github.com/rcore-os/aarch64" } bcm2837 = { git = "https://github.com/rcore-os/bcm2837", optional = true } [target.'cfg(target_arch = "mips")'.dependencies] -mips = "^0.1.0" +mips = { git = "https://github.com/Harry-Chen/rust-mips" } [package.metadata.bootimage] default-target = "targets/x86_64.json" diff --git a/kernel/src/arch/mipsel/board/malta/fb.rs b/kernel/src/arch/mipsel/board/malta/fb.rs deleted file mode 100644 index f466bfa..0000000 --- a/kernel/src/arch/mipsel/board/malta/fb.rs +++ /dev/null @@ -1,13 +0,0 @@ -//! stub frame buffer driver for malta board - -use spin::Mutex; - -lazy_static! { - pub static ref FRAME_BUFFER: Mutex> = Mutex::new(None); -} - -pub struct Framebuffer {} - -pub struct FramebufferInfo {} - -pub enum ColorDepth {} \ No newline at end of file diff --git a/kernel/src/arch/mipsel/board/malta/mod.rs b/kernel/src/arch/mipsel/board/malta/mod.rs index 0a3f750..f5f892a 100644 --- a/kernel/src/arch/mipsel/board/malta/mod.rs +++ b/kernel/src/arch/mipsel/board/malta/mod.rs @@ -1,6 +1,8 @@ use once::*; +use alloc::string::String; pub mod serial; +#[path = "../../../../drivers/gpu/fb.rs"] pub mod fb; #[path = "../../../../drivers/console/mod.rs"] pub mod console; @@ -16,4 +18,8 @@ pub fn init_serial_early() { pub fn init_driver() { // TODO: add possibly more drivers // timer::init(); +} + +pub fn probe_fb_info(width: u32, height: u32, depth: u32) -> Result<(fb::FramebufferInfo, usize), String> { + Err(String::from("Framebuffer not usable on malta board")) } \ No newline at end of file diff --git a/kernel/src/arch/mipsel/board/malta/serial.rs b/kernel/src/arch/mipsel/board/malta/serial.rs index b9b7fe0..5e9a638 100644 --- a/kernel/src/arch/mipsel/board/malta/serial.rs +++ b/kernel/src/arch/mipsel/board/malta/serial.rs @@ -34,7 +34,7 @@ impl SerialPort { } /// non-blocking version of putchar() - fn putchar(&mut self, c: u8) { + pub fn putchar(&mut self, c: u8) { write(self.base + COM_TX, c); } @@ -88,7 +88,7 @@ fn write(addr: usize, content: T) { fn read(addr: usize) -> T { let cell = (addr) as *const T; - read_volatile(cell); + read_volatile(cell) } diff --git a/kernel/src/arch/mipsel/board/thinpad/mod.rs b/kernel/src/arch/mipsel/board/thinpad/mod.rs index 6c480f4..a290559 100644 --- a/kernel/src/arch/mipsel/board/thinpad/mod.rs +++ b/kernel/src/arch/mipsel/board/thinpad/mod.rs @@ -19,7 +19,7 @@ pub fn init_driver() { // timer::init(); } -pub fn probe_fb_info(width: u32, height: u32, depth: u32) -> Result<(FramebufferInfo, u32), String> { +pub fn probe_fb_info(width: u32, height: u32, depth: u32) -> Result<(FramebufferInfo, usize), String> { let fb_info = FramebufferInfo { xres: 800, yres: 600, diff --git a/kernel/src/arch/mipsel/mod.rs b/kernel/src/arch/mipsel/mod.rs index e8c3fe0..c3f4692 100644 --- a/kernel/src/arch/mipsel/mod.rs +++ b/kernel/src/arch/mipsel/mod.rs @@ -72,7 +72,7 @@ fn others_main() -> ! { crate::kmain(); } -const BOOT_CPU_ID: usize = 0; +const BOOT_CPU_ID: u32 = 0; global_asm!(include_str!("boot/entry.S")); global_asm!(include_str!("boot/trap.S")); From 747d5e2bee9b1915fecbe0de33ab54437f53c115 Mon Sep 17 00:00:00 2001 From: Yuhao Zhou Date: Fri, 5 Apr 2019 23:31:30 +0800 Subject: [PATCH 29/85] Fix many errors. --- kernel/src/arch/mipsel/board/malta/serial.rs | 8 +++---- kernel/src/arch/mipsel/boot/trap.S | 8 +++++++ kernel/src/arch/mipsel/context.rs | 7 ++++-- kernel/src/arch/mipsel/paging.rs | 24 ++++++++++++-------- kernel/src/backtrace.rs | 8 ++++++- 5 files changed, 39 insertions(+), 16 deletions(-) diff --git a/kernel/src/arch/mipsel/board/malta/serial.rs b/kernel/src/arch/mipsel/board/malta/serial.rs index 5e9a638..2618e0d 100644 --- a/kernel/src/arch/mipsel/board/malta/serial.rs +++ b/kernel/src/arch/mipsel/board/malta/serial.rs @@ -4,7 +4,7 @@ use core::fmt::{Write, Result, Arguments}; use core::ptr::{read_volatile, write_volatile}; use spin::Mutex; -struct SerialPort { +pub struct SerialPort { base: usize } @@ -83,12 +83,12 @@ impl Write for SerialPort { fn write(addr: usize, content: T) { let cell = (addr) as *mut T; - write_volatile(cell, content); + unsafe { write_volatile(cell, content) } } fn read(addr: usize) -> T { let cell = (addr) as *const T; - read_volatile(cell) + unsafe { read_volatile(cell) } } @@ -119,4 +119,4 @@ lazy_static! { pub fn init(base: usize) { SERIAL_PORT.lock().init(base); -} \ No newline at end of file +} diff --git a/kernel/src/arch/mipsel/boot/trap.S b/kernel/src/arch/mipsel/boot/trap.S index f6d891e..513b9cd 100644 --- a/kernel/src/arch/mipsel/boot/trap.S +++ b/kernel/src/arch/mipsel/boot/trap.S @@ -156,3 +156,11 @@ kernel_stack: .space 1024 * 16 # 16KB for kernel stack .global kernel_stack_top kernel_stack_top: + + .align 12 #PGSHIFT + .global root_page_table_buffer +root_page_table_buffer: + .space 1024 * 4 # 4KB + .global root_page_table_ptr +root_page_table_ptr: + .space 4 # 4bytes diff --git a/kernel/src/arch/mipsel/context.rs b/kernel/src/arch/mipsel/context.rs index c968874..bb3dba4 100644 --- a/kernel/src/arch/mipsel/context.rs +++ b/kernel/src/arch/mipsel/context.rs @@ -1,5 +1,8 @@ use mips::registers::cp0; -use crate::arch::paging::root_page_table_ptr; + +extern { + static root_page_table_ptr : *mut usize; +} /// Saved registers on a trap. #[derive(Clone)] @@ -206,7 +209,7 @@ impl Context { Store zero, 0(a1) jr ra nop" - :"=r"(root_page_table_ptr) :"r"(root_page_table_ptr) : : "volatile" ) + :"=r"(*root_page_table_ptr) :"r"(*root_page_table_ptr) : : "volatile" ) } /// Constructs a null Context for the current running thread. diff --git a/kernel/src/arch/mipsel/paging.rs b/kernel/src/arch/mipsel/paging.rs index 3cc63c3..3ea5a7a 100644 --- a/kernel/src/arch/mipsel/paging.rs +++ b/kernel/src/arch/mipsel/paging.rs @@ -49,14 +49,15 @@ impl PageTable for ActivePageTable { impl PageTableExt for ActivePageTable {} /// The virtual address of root page table -static ROOT_PAGE_TABLE_BUFFER: MIPSPageTable = ::core::mem::uninitialized(); -pub static mut root_page_table_ptr: usize = - &ROOT_PAGE_TABLE_BUFFER as *const MIPSPageTable as usize; +extern { + static root_page_table_buffer : *mut MIPSPageTable; + static root_page_table_ptr : *mut usize; +} impl ActivePageTable { pub unsafe fn new() -> Self { ActivePageTable( - TwoLevelPageTable::new(&mut ROOT_PAGE_TABLE_BUFFER), + TwoLevelPageTable::new(&mut *(root_page_table_buffer as *mut MIPSPageTable)), ::core::mem::uninitialized() ) } @@ -119,11 +120,11 @@ impl InactivePageTable for InactivePageTable0 { } unsafe fn set_token(token: usize) { - root_page_table_ptr = token; + *root_page_table_ptr = token; } fn active_token() -> usize { - root_page_table_ptr + unsafe { *root_page_table_ptr } } fn flush_tlb() { @@ -131,11 +132,16 @@ impl InactivePageTable for InactivePageTable0 { } fn edit(&mut self, f: impl FnOnce(&mut Self::Active) -> T) -> T { - let pt: *mut MIPSPageTable = self.token() as *mut MIPSPageTable; - let active = ActivePageTable( + let pt: *mut MIPSPageTable = unsafe { + self.token() as *mut MIPSPageTable + }; + + let mut active = unsafe { + ActivePageTable( TwoLevelPageTable::new(&mut *pt), ::core::mem::uninitialized() - ); + ) + }; f(&mut active) } } diff --git a/kernel/src/backtrace.rs b/kernel/src/backtrace.rs index a4b4ecf..d72a372 100644 --- a/kernel/src/backtrace.rs +++ b/kernel/src/backtrace.rs @@ -22,6 +22,10 @@ pub fn fp() -> usize { unsafe { asm!("mov %rbp, $0" : "=r"(ptr)); } + #[cfg(any(target_arch = "mips"))] + unsafe { + asm!("mov $0, fp" : "=r"(ptr)); + } ptr } @@ -34,7 +38,9 @@ pub fn lr() -> usize { unsafe { asm!("mov $0, x30" : "=r"(ptr)); } - #[cfg(any(target_arch = "riscv32", target_arch = "riscv64"))] + #[cfg(any(target_arch = "riscv32", + target_arch = "riscv64", + target_arch = "mips"))] unsafe { asm!("mv $0, ra" : "=r"(ptr)); } From 8ed6822636a5807be34d97257683e6de812fc6ab Mon Sep 17 00:00:00 2001 From: Yuhao Zhou Date: Sat, 6 Apr 2019 00:04:56 +0800 Subject: [PATCH 30/85] Move context switch to context.S --- kernel/src/arch/mipsel/boot/context.S | 54 +++++++++++++++++++++++++++ kernel/src/arch/mipsel/context.rs | 52 +------------------------- 2 files changed, 55 insertions(+), 51 deletions(-) create mode 100644 kernel/src/arch/mipsel/boot/context.S diff --git a/kernel/src/arch/mipsel/boot/context.S b/kernel/src/arch/mipsel/boot/context.S new file mode 100644 index 0000000..de94380 --- /dev/null +++ b/kernel/src/arch/mipsel/boot/context.S @@ -0,0 +1,54 @@ +#include "regdef.h" + +.set noat +.set noreorder + +// .section .text.context +.globl switch_context +.extern root_page_table_ptr + +switch_context: + // save from's registers + addi sp, sp, (-4*14) + sw sp, 0(a0) + sw ra, 0(sp) + sw s0, 2*4(sp) + sw s1, 3*4(sp) + sw s2, 4*4(sp) + sw s3, 5*4(sp) + sw s4, 6*4(sp) + sw s5, 7*4(sp) + sw s6, 8*4(sp) + sw s7, 9*4(sp) + sw s8, 10*4(sp) + sw gp, 11*4(sp) + sw ra, 12*4(sp) + sw sp, 13*4(sp) + + la s0, root_page_table_ptr + lw at, 0(s0) + sw at, 4(sp) + + // restore to's registers + lw sp, 0(a1) + lw at, 4(sp) + sw at, 0(s0) + + lw ra, 0(sp) + lw s0, 2*4(sp) + lw s1, 3*4(sp) + lw s2, 4*4(sp) + lw s3, 5*4(sp) + lw s4, 6*4(sp) + lw s5, 7*4(sp) + lw s6, 8*4(sp) + lw s7, 9*4(sp) + lw s8, 10*4(sp) + lw gp, 11*4(sp) + lw ra, 12*4(sp) + lw sp, 13*4(sp) + addi sp, sp, (4*14) + + sw zero, 0(a1) + jr ra + nop diff --git a/kernel/src/arch/mipsel/context.rs b/kernel/src/arch/mipsel/context.rs index bb3dba4..c44509c 100644 --- a/kernel/src/arch/mipsel/context.rs +++ b/kernel/src/arch/mipsel/context.rs @@ -159,57 +159,7 @@ impl Context { #[naked] #[inline(never)] pub unsafe extern fn switch(&mut self, _target: &mut Self) { - asm!(r" - .equ XLENB, 4 - .macro Load reg, mem - lw \reg, \mem - .endm - .macro Store reg, mem - sw \reg, \mem - .endm"); - asm!(" - // save from's registers - addi sp, sp, (-XLENB*14) - Store sp, 0(a0) - Store ra, 0*XLENB(sp) - Store s0, 2*XLENB(sp) - Store s1, 3*XLENB(sp) - Store s2, 4*XLENB(sp) - Store s3, 5*XLENB(sp) - Store s4, 6*XLENB(sp) - Store s5, 7*XLENB(sp) - Store s6, 8*XLENB(sp) - Store s7, 9*XLENB(sp) - Store s8, 10*XLENB(sp) - Store gp, 11*XLENB(sp) - Store ra, 12*XLENB(sp) - Store sp, 13*XLENB(sp) - - Store $1, 1*XLENB(sp) - - // restore to's registers - Load sp, 0(a1) - Load $0, 1*XLENB(sp) - - Load ra, 0*XLENB(sp) - Load s0, 2*XLENB(sp) - Load s1, 3*XLENB(sp) - Load s2, 4*XLENB(sp) - Load s3, 5*XLENB(sp) - Load s4, 6*XLENB(sp) - Load s5, 7*XLENB(sp) - Load s6, 8*XLENB(sp) - Load s7, 9*XLENB(sp) - Load s8, 10*XLENB(sp) - Load gp, 11*XLENB(sp) - Load ra, 12*XLENB(sp) - Load sp, 13*XLENB(sp) - addi sp, sp, (XLENB*14) - - Store zero, 0(a1) - jr ra - nop" - :"=r"(*root_page_table_ptr) :"r"(*root_page_table_ptr) : : "volatile" ) + asm!(include_str!("boot/context.S")); } /// Constructs a null Context for the current running thread. From 65d6fb5b1ee8dfda102ece8873c8b783f575747f Mon Sep 17 00:00:00 2001 From: Harry Chen Date: Sat, 6 Apr 2019 00:24:01 +0800 Subject: [PATCH 31/85] Use gcc to pre-process mipsel assembly Signed-off-by: Harry Chen --- .gitignore | 2 +- kernel/Makefile | 3 +++ kernel/build.rs | 3 +-- kernel/src/arch/mipsel/boot/entry.S | 11 ++++++----- kernel/src/arch/mipsel/context.rs | 2 +- kernel/src/arch/mipsel/mod.rs | 6 +++--- 6 files changed, 15 insertions(+), 12 deletions(-) diff --git a/.gitignore b/.gitignore index dc3bbf3..4b4a5a8 100644 --- a/.gitignore +++ b/.gitignore @@ -1,7 +1,7 @@ build target /kernel/src/arch/x86_64/interrupt/vector.asm -/kernel/src/arch/*/boot/dtb.S +*.gen.s *.dtb Cargo.lock diff --git a/kernel/Makefile b/kernel/Makefile index 07d5259..182f78f 100644 --- a/kernel/Makefile +++ b/kernel/Makefile @@ -317,6 +317,9 @@ else ifeq ($(arch), riscv64) else ifeq ($(arch), aarch64) @cargo xbuild $(build_args) else ifeq ($(arch), mipsel) + @for file in context entry trap ; do \ + $(cc) -E src/arch/$(arch)/boot/$${file}.S -o src/arch/$(arch)/boot/$${file}.gen.s ; \ + done @cargo xbuild $(build_args) endif diff --git a/kernel/build.rs b/kernel/build.rs index 3efcadb..6390c32 100644 --- a/kernel/build.rs +++ b/kernel/build.rs @@ -60,13 +60,12 @@ fn gen_dtb_asm(arch: &String, _board: &String) -> Result<()> { panic!("DTB `{}` not found", dtb) } - let mut f = File::create(format!("src/arch/{}/boot/dtb.S", arch)).unwrap(); + let mut f = File::create(format!("src/arch/{}/boot/dtb.gen.s", arch)).unwrap(); println!("cargo:rerun-if-changed={}", dtb); println!("cargo:rerun-if-env-changed=DTB"); writeln!(f, "# generated by build.rs - do not edit")?; - writeln!(f, ".intel_syntax noprefix")?; write!(f, r#" .section .dtb,"a" .align 12 diff --git a/kernel/src/arch/mipsel/boot/entry.S b/kernel/src/arch/mipsel/boot/entry.S index 0d0e70b..019006c 100644 --- a/kernel/src/arch/mipsel/boot/entry.S +++ b/kernel/src/arch/mipsel/boot/entry.S @@ -11,14 +11,15 @@ _start: # set ebase la t0, trap_entry - mfc0 t1, 15 # C0_EBASE + mfc0 t1, $15 # C0_EBASE or t1, t1, t0 - mtc0 t1, 15 + mtc0 t1, $15 # exit bootstrap mode - mfc0 t0, 12 # C0_STATUS - andi t0, t0, 0xFFBFFFFF # set BEV (bit 22) to 0 - mtc0 t0, 12 + mfc0 t0, $12 # C0_STATUS + li t1, 0xFFBFFFFF # set BEV (bit 22) to 0 + and t0, t0, t1 + mtc0 t0, $12 # directly jump to main function b rust_main diff --git a/kernel/src/arch/mipsel/context.rs b/kernel/src/arch/mipsel/context.rs index c44509c..bcb5702 100644 --- a/kernel/src/arch/mipsel/context.rs +++ b/kernel/src/arch/mipsel/context.rs @@ -159,7 +159,7 @@ impl Context { #[naked] #[inline(never)] pub unsafe extern fn switch(&mut self, _target: &mut Self) { - asm!(include_str!("boot/context.S")); + asm!(include_str!("boot/context.gen.s")); } /// Constructs a null Context for the current running thread. diff --git a/kernel/src/arch/mipsel/mod.rs b/kernel/src/arch/mipsel/mod.rs index c3f4692..ce90f55 100644 --- a/kernel/src/arch/mipsel/mod.rs +++ b/kernel/src/arch/mipsel/mod.rs @@ -74,6 +74,6 @@ fn others_main() -> ! { const BOOT_CPU_ID: u32 = 0; -global_asm!(include_str!("boot/entry.S")); -global_asm!(include_str!("boot/trap.S")); -global_asm!(include_str!("boot/dtb.S")); +global_asm!(include_str!("boot/entry.gen.s")); +global_asm!(include_str!("boot/trap.gen.s")); +global_asm!(include_str!("boot/dtb.gen.s")); From 1afacc4164f66853a8d9b1816f00be6c703b8d7c Mon Sep 17 00:00:00 2001 From: Harry Chen Date: Sat, 6 Apr 2019 00:37:10 +0800 Subject: [PATCH 32/85] Fix AT register in context.S Signed-off-by: Harry Chen --- kernel/src/arch/mipsel/boot/context.S | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/kernel/src/arch/mipsel/boot/context.S b/kernel/src/arch/mipsel/boot/context.S index de94380..6da03c6 100644 --- a/kernel/src/arch/mipsel/boot/context.S +++ b/kernel/src/arch/mipsel/boot/context.S @@ -26,13 +26,13 @@ switch_context: sw sp, 13*4(sp) la s0, root_page_table_ptr - lw at, 0(s0) - sw at, 4(sp) + lw AT, 0(s0) + sw AT, 4(sp) // restore to's registers lw sp, 0(a1) - lw at, 4(sp) - sw at, 0(s0) + lw AT, 4(sp) + sw AT, 0(s0) lw ra, 0(sp) lw s0, 2*4(sp) From 8e01458ae0b76dbf35f74f46834f02e052993a3d Mon Sep 17 00:00:00 2001 From: Harry Chen Date: Sat, 6 Apr 2019 00:38:36 +0800 Subject: [PATCH 33/85] Update user app repo Signed-off-by: Harry Chen --- user | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/user b/user index 97bae0c..67890ae 160000 --- a/user +++ b/user @@ -1 +1 @@ -Subproject commit 97bae0c39a7aeaab07654d99c3ba3bcb4d01658c +Subproject commit 67890aeb4205083d5a95b1f70de92ae39b549c8c From c9980f1efb7dfbd177cf724984357265ca430390 Mon Sep 17 00:00:00 2001 From: Yuhao Zhou Date: Sat, 6 Apr 2019 00:45:41 +0800 Subject: [PATCH 34/85] Fix context switch. --- kernel/src/arch/mipsel/boot/context.S | 2 +- kernel/src/arch/mipsel/boot/dtb.S | 10 ++++++++++ kernel/src/arch/mipsel/context.rs | 6 +++++- kernel/src/arch/mipsel/mod.rs | 1 + kernel/src/backtrace.rs | 11 ++++++++--- 5 files changed, 25 insertions(+), 5 deletions(-) create mode 100644 kernel/src/arch/mipsel/boot/dtb.S diff --git a/kernel/src/arch/mipsel/boot/context.S b/kernel/src/arch/mipsel/boot/context.S index 6da03c6..86c9a85 100644 --- a/kernel/src/arch/mipsel/boot/context.S +++ b/kernel/src/arch/mipsel/boot/context.S @@ -3,7 +3,7 @@ .set noat .set noreorder -// .section .text.context +.section .text.context .globl switch_context .extern root_page_table_ptr diff --git a/kernel/src/arch/mipsel/boot/dtb.S b/kernel/src/arch/mipsel/boot/dtb.S new file mode 100644 index 0000000..eea7469 --- /dev/null +++ b/kernel/src/arch/mipsel/boot/dtb.S @@ -0,0 +1,10 @@ +# generated by build.rs - do not edit +.intel_syntax noprefix + + .section .dtb,"a" + .align 12 + .global _dtb_start, _dtb_end +_dtb_start: + .incbin "src/arch/mipsel/board/malta/device.dtb" +_dtb_end: + \ No newline at end of file diff --git a/kernel/src/arch/mipsel/context.rs b/kernel/src/arch/mipsel/context.rs index bcb5702..1a53b7d 100644 --- a/kernel/src/arch/mipsel/context.rs +++ b/kernel/src/arch/mipsel/context.rs @@ -159,7 +159,11 @@ impl Context { #[naked] #[inline(never)] pub unsafe extern fn switch(&mut self, _target: &mut Self) { - asm!(include_str!("boot/context.gen.s")); + extern { + fn switch_context(src : &mut Context, dst : &mut Context); + } + + switch_context(self, _target); } /// Constructs a null Context for the current running thread. diff --git a/kernel/src/arch/mipsel/mod.rs b/kernel/src/arch/mipsel/mod.rs index ce90f55..e4d78b0 100644 --- a/kernel/src/arch/mipsel/mod.rs +++ b/kernel/src/arch/mipsel/mod.rs @@ -74,6 +74,7 @@ fn others_main() -> ! { const BOOT_CPU_ID: u32 = 0; +global_asm!(include_str!("boot/context.gen.s")); global_asm!(include_str!("boot/entry.gen.s")); global_asm!(include_str!("boot/trap.gen.s")); global_asm!(include_str!("boot/dtb.gen.s")); diff --git a/kernel/src/backtrace.rs b/kernel/src/backtrace.rs index d72a372..5d84f7f 100644 --- a/kernel/src/backtrace.rs +++ b/kernel/src/backtrace.rs @@ -24,7 +24,8 @@ pub fn fp() -> usize { } #[cfg(any(target_arch = "mips"))] unsafe { - asm!("mov $0, fp" : "=r"(ptr)); + // fp = $30 + asm!("ori $0, $$$30, 0" : "=r"(ptr)); } ptr @@ -39,8 +40,7 @@ pub fn lr() -> usize { asm!("mov $0, x30" : "=r"(ptr)); } #[cfg(any(target_arch = "riscv32", - target_arch = "riscv64", - target_arch = "mips"))] + target_arch = "riscv64"))] unsafe { asm!("mv $0, ra" : "=r"(ptr)); } @@ -49,6 +49,11 @@ pub fn lr() -> usize { asm!("movq 8(%rbp), $0" : "=r"(ptr)); } + #[cfg(target_arch = "mips")] + unsafe { + asm!("ori $0, $$$31, 0" : "=r"(ptr)); + } + ptr } From 7c20ebf6e0e85392508663ae88da73e0ea44fe20 Mon Sep 17 00:00:00 2001 From: Yuhao Zhou Date: Sat, 6 Apr 2019 00:48:24 +0800 Subject: [PATCH 35/85] Remove dtb.S. --- kernel/src/arch/mipsel/boot/dtb.S | 10 ---------- 1 file changed, 10 deletions(-) delete mode 100644 kernel/src/arch/mipsel/boot/dtb.S diff --git a/kernel/src/arch/mipsel/boot/dtb.S b/kernel/src/arch/mipsel/boot/dtb.S deleted file mode 100644 index eea7469..0000000 --- a/kernel/src/arch/mipsel/boot/dtb.S +++ /dev/null @@ -1,10 +0,0 @@ -# generated by build.rs - do not edit -.intel_syntax noprefix - - .section .dtb,"a" - .align 12 - .global _dtb_start, _dtb_end -_dtb_start: - .incbin "src/arch/mipsel/board/malta/device.dtb" -_dtb_end: - \ No newline at end of file From f5227e28d3d2470debaf0ce85a9ad07821ee8a46 Mon Sep 17 00:00:00 2001 From: Harry Chen Date: Sat, 6 Apr 2019 00:55:08 +0800 Subject: [PATCH 36/85] Fix register naming in backtrace Signed-off-by: Harry Chen --- kernel/src/arch/mipsel/context.rs | 11 +++++------ kernel/src/backtrace.rs | 4 ++-- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/kernel/src/arch/mipsel/context.rs b/kernel/src/arch/mipsel/context.rs index 1a53b7d..372a186 100644 --- a/kernel/src/arch/mipsel/context.rs +++ b/kernel/src/arch/mipsel/context.rs @@ -156,14 +156,13 @@ impl Context { /// Push all callee-saved registers at the current kernel stack. /// Store current sp, switch to target. /// Pop all callee-saved registers, then return to the target. - #[naked] - #[inline(never)] - pub unsafe extern fn switch(&mut self, _target: &mut Self) { - extern { - fn switch_context(src : &mut Context, dst : &mut Context); + #[inline(always)] + pub unsafe fn switch(&mut self, target: &mut Self) { + extern "C" { + fn switch_context(src: *mut Context, dst: *mut Context); } - switch_context(self, _target); + switch_context(self as *mut Context, target as *mut Context); } /// Constructs a null Context for the current running thread. diff --git a/kernel/src/backtrace.rs b/kernel/src/backtrace.rs index 5d84f7f..af1b045 100644 --- a/kernel/src/backtrace.rs +++ b/kernel/src/backtrace.rs @@ -25,7 +25,7 @@ pub fn fp() -> usize { #[cfg(any(target_arch = "mips"))] unsafe { // fp = $30 - asm!("ori $0, $$$30, 0" : "=r"(ptr)); + asm!("ori $0, $$30, 0" : "=r"(ptr)); } ptr @@ -51,7 +51,7 @@ pub fn lr() -> usize { #[cfg(target_arch = "mips")] unsafe { - asm!("ori $0, $$$31, 0" : "=r"(ptr)); + asm!("ori $0, $$31, 0" : "=r"(ptr)); } ptr From 06f7b1643d833ba83373bd076ca1d37b9de02383 Mon Sep 17 00:00:00 2001 From: Harry Chen Date: Sat, 6 Apr 2019 00:58:32 +0800 Subject: [PATCH 37/85] Fix makefile options for mipsel Signed-off-by: Harry Chen --- kernel/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/Makefile b/kernel/Makefile index 182f78f..b156828 100644 --- a/kernel/Makefile +++ b/kernel/Makefile @@ -295,7 +295,7 @@ else ifeq ($(arch), aarch64) else ifeq ($(arch), mipsel) # qemu-system-mipsel accepts ELF file only, so don't use objcopy @cp $(kernel) $(kernel)_orig - @$(strip) $(kernel) -o $(kernel) + @$(strip) $(kernel) -o $@ endif kernel: $(dtb) From 610fd5b3db221e86105add28e1e90bb59111dd41 Mon Sep 17 00:00:00 2001 From: Yuhao Zhou Date: Sat, 6 Apr 2019 01:01:10 +0800 Subject: [PATCH 38/85] Fix MIPS registers access in backtrace.rs. --- kernel/src/arch/mipsel/context.rs | 3 +-- kernel/src/backtrace.rs | 6 +++--- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/kernel/src/arch/mipsel/context.rs b/kernel/src/arch/mipsel/context.rs index 1a53b7d..000b106 100644 --- a/kernel/src/arch/mipsel/context.rs +++ b/kernel/src/arch/mipsel/context.rs @@ -156,8 +156,7 @@ impl Context { /// Push all callee-saved registers at the current kernel stack. /// Store current sp, switch to target. /// Pop all callee-saved registers, then return to the target. - #[naked] - #[inline(never)] + #[inline(always)] pub unsafe extern fn switch(&mut self, _target: &mut Self) { extern { fn switch_context(src : &mut Context, dst : &mut Context); diff --git a/kernel/src/backtrace.rs b/kernel/src/backtrace.rs index 5d84f7f..8d6c178 100644 --- a/kernel/src/backtrace.rs +++ b/kernel/src/backtrace.rs @@ -24,8 +24,8 @@ pub fn fp() -> usize { } #[cfg(any(target_arch = "mips"))] unsafe { - // fp = $30 - asm!("ori $0, $$$30, 0" : "=r"(ptr)); + // fp = s8 = $30 + asm!("ori $0, $$$1, 0" : "=r"(ptr): "i"(30)); } ptr @@ -51,7 +51,7 @@ pub fn lr() -> usize { #[cfg(target_arch = "mips")] unsafe { - asm!("ori $0, $$$31, 0" : "=r"(ptr)); + asm!("ori $0, $$$1, 0" : "=r"(ptr) : "i"(31)); } ptr From c3e94d38ae87358bba85fa06fd4e226f47602c24 Mon Sep 17 00:00:00 2001 From: Harry Chen Date: Sat, 6 Apr 2019 01:57:23 +0800 Subject: [PATCH 39/85] Fix early uart on malta, now malta board can print things! Signed-off-by: Harry Chen --- kernel/Makefile | 2 +- kernel/src/arch/mipsel/board/malta/device.dts | 6 ++++++ kernel/src/arch/mipsel/board/malta/mod.rs | 2 +- 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/kernel/Makefile b/kernel/Makefile index b156828..ec9f892 100644 --- a/kernel/Makefile +++ b/kernel/Makefile @@ -127,7 +127,7 @@ else ifeq ($(arch), mipsel) ifeq ($(board), malta) qemu_opts += \ -machine $(board) \ - -serial none -serial none -serial mon:stdio \ + -serial mon:stdio \ -kernel $(kernel_img) endif endif diff --git a/kernel/src/arch/mipsel/board/malta/device.dts b/kernel/src/arch/mipsel/board/malta/device.dts index c68424b..ddaaa72 100644 --- a/kernel/src/arch/mipsel/board/malta/device.dts +++ b/kernel/src/arch/mipsel/board/malta/device.dts @@ -24,6 +24,12 @@ reg = <0x00000000 0x10000000>; }; + uart0: serial@b80003f8 { + compatible = "ns16550a"; + reg = <0xb80003f8 0x8>; + clock-frequency = <1843200>; + }; + uart2: serial@bf000900 { compatible = "ns16550a"; reg = <0xbf000900 0x40>; diff --git a/kernel/src/arch/mipsel/board/malta/mod.rs b/kernel/src/arch/mipsel/board/malta/mod.rs index f5f892a..d9b9d0b 100644 --- a/kernel/src/arch/mipsel/board/malta/mod.rs +++ b/kernel/src/arch/mipsel/board/malta/mod.rs @@ -10,7 +10,7 @@ pub mod console; /// Initialize serial port first pub fn init_serial_early() { assert_has_not_been_called!("board::init must be called only once"); - serial::init(0xbf000900); + serial::init(0xb80003f8); println!("Hello QEMU Malta!"); } From cbb44312319b941883cdaeec3224666a51a7b33f Mon Sep 17 00:00:00 2001 From: Yuhao Zhou Date: Sat, 6 Apr 2019 02:10:30 +0800 Subject: [PATCH 40/85] Fix memory size. --- kernel/src/arch/mipsel/consts.rs | 2 +- kernel/src/memory.rs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/kernel/src/arch/mipsel/consts.rs b/kernel/src/arch/mipsel/consts.rs index 78f71db..ab7bf18 100644 --- a/kernel/src/arch/mipsel/consts.rs +++ b/kernel/src/arch/mipsel/consts.rs @@ -5,7 +5,7 @@ pub const KERNEL_OFFSET: usize = 0x80100000; pub const KERNEL_HEAP_SIZE: usize = 0x00a0_0000; pub const MEMORY_OFFSET: usize = 0x8000_0000; -pub const MEMORY_END: usize = 0x8100_0000; +pub const MEMORY_END: usize = 0x8800_0000; pub const USER_STACK_OFFSET: usize = 0x80000000 - USER_STACK_SIZE; pub const USER_STACK_SIZE: usize = 0x10000; diff --git a/kernel/src/memory.rs b/kernel/src/memory.rs index c6a34f0..2fb5308 100644 --- a/kernel/src/memory.rs +++ b/kernel/src/memory.rs @@ -17,11 +17,11 @@ pub type MemorySet = rcore_memory::memory_set::MemorySet; pub type FrameAlloc = bit_allocator::BitAlloc16M; // RISCV has 8M memory -#[cfg(any(target_arch = "riscv32", target_arch = "riscv64", target_arch = "mips"))] +#[cfg(any(target_arch = "riscv32", target_arch = "riscv64"))] pub type FrameAlloc = bit_allocator::BitAlloc4K; // Raspberry Pi 3 has 1G memory -#[cfg(target_arch = "aarch64")] +#[cfg(any(target_arch = "aarch64", target_arch = "mips"))] pub type FrameAlloc = bit_allocator::BitAlloc1M; lazy_static! { From 96caa809141d279ff71b4b5fea74bf62206291a0 Mon Sep 17 00:00:00 2001 From: Harry Chen Date: Sat, 6 Apr 2019 02:20:49 +0800 Subject: [PATCH 41/85] Extract some board-specfic constants Signed-off-by: Harry Chen --- kernel/src/arch/mipsel/board/malta/consts.rs | 3 +++ kernel/src/arch/mipsel/board/malta/mod.rs | 1 + kernel/src/arch/mipsel/board/malta/serial.rs | 2 +- kernel/src/arch/mipsel/board/thinpad/consts.rs | 3 +++ kernel/src/arch/mipsel/board/thinpad/mod.rs | 6 +++++- kernel/src/arch/mipsel/board/thinpad/serial.rs | 8 ++++---- kernel/src/arch/mipsel/boot/linker.ld | 2 +- kernel/src/arch/mipsel/consts.rs | 6 +++--- 8 files changed, 21 insertions(+), 10 deletions(-) create mode 100644 kernel/src/arch/mipsel/board/malta/consts.rs create mode 100644 kernel/src/arch/mipsel/board/thinpad/consts.rs diff --git a/kernel/src/arch/mipsel/board/malta/consts.rs b/kernel/src/arch/mipsel/board/malta/consts.rs new file mode 100644 index 0000000..5f1f8f5 --- /dev/null +++ b/kernel/src/arch/mipsel/board/malta/consts.rs @@ -0,0 +1,3 @@ +/// board specific constants for malta +pub const MEMORY_END: usize = 0x8800_0000; +pub const KERNEL_HEAP_SIZE: usize = 0x00a0_0000; diff --git a/kernel/src/arch/mipsel/board/malta/mod.rs b/kernel/src/arch/mipsel/board/malta/mod.rs index d9b9d0b..05b27b7 100644 --- a/kernel/src/arch/mipsel/board/malta/mod.rs +++ b/kernel/src/arch/mipsel/board/malta/mod.rs @@ -6,6 +6,7 @@ pub mod serial; pub mod fb; #[path = "../../../../drivers/console/mod.rs"] pub mod console; +pub mod consts; /// Initialize serial port first pub fn init_serial_early() { diff --git a/kernel/src/arch/mipsel/board/malta/serial.rs b/kernel/src/arch/mipsel/board/malta/serial.rs index 2618e0d..b624729 100644 --- a/kernel/src/arch/mipsel/board/malta/serial.rs +++ b/kernel/src/arch/mipsel/board/malta/serial.rs @@ -83,7 +83,7 @@ impl Write for SerialPort { fn write(addr: usize, content: T) { let cell = (addr) as *mut T; - unsafe { write_volatile(cell, content) } + unsafe { write_volatile(cell, content); } } fn read(addr: usize) -> T { diff --git a/kernel/src/arch/mipsel/board/thinpad/consts.rs b/kernel/src/arch/mipsel/board/thinpad/consts.rs new file mode 100644 index 0000000..9a10cde --- /dev/null +++ b/kernel/src/arch/mipsel/board/thinpad/consts.rs @@ -0,0 +1,3 @@ +/// board specific constants for thinpad +pub const MEMORY_END: usize = 0x8080_0000; +pub const KERNEL_HEAP_SIZE: usize = 0x0020_0000; diff --git a/kernel/src/arch/mipsel/board/thinpad/mod.rs b/kernel/src/arch/mipsel/board/thinpad/mod.rs index a290559..358197f 100644 --- a/kernel/src/arch/mipsel/board/thinpad/mod.rs +++ b/kernel/src/arch/mipsel/board/thinpad/mod.rs @@ -1,10 +1,14 @@ use once::*; +use alloc::string::String; pub mod serial; #[path = "../../../../drivers/gpu/fb.rs"] pub mod fb; #[path = "../../../../drivers/console/mod.rs"] pub mod console; +pub mod consts; + +use fb::FramebufferInfo; /// Initialize serial port first pub fn init_serial_early() { @@ -31,6 +35,6 @@ pub fn probe_fb_info(width: u32, height: u32, depth: u32) -> Result<(Framebuffer pitch: 800, bus_addr: 0xa2000000, screen_size: 800 * 600, - } + }; Ok((fb_info, 0xa2000000)) } \ No newline at end of file diff --git a/kernel/src/arch/mipsel/board/thinpad/serial.rs b/kernel/src/arch/mipsel/board/thinpad/serial.rs index 3c59a0d..95c693d 100644 --- a/kernel/src/arch/mipsel/board/thinpad/serial.rs +++ b/kernel/src/arch/mipsel/board/thinpad/serial.rs @@ -4,7 +4,7 @@ use core::fmt::{Write, Result, Arguments}; use core::ptr::{read_volatile, write_volatile}; use spin::Mutex; -struct SerialPort { +pub struct SerialPort { base: usize } @@ -27,7 +27,7 @@ impl SerialPort { } /// non-blocking version of putchar() - fn putchar(&mut self, c: u8) { + pub fn putchar(&mut self, c: u8) { write(self.base + UART_DATA, c); } @@ -76,12 +76,12 @@ impl Write for SerialPort { fn write(addr: usize, content: T) { let cell = (addr) as *mut T; - write_volatile(cell, content); + unsafe { write_volatile(cell, content); } } fn read(addr: usize) -> T { let cell = (addr) as *const T; - read_volatile(cell); + unsafe { read_volatile(cell) } } diff --git a/kernel/src/arch/mipsel/boot/linker.ld b/kernel/src/arch/mipsel/boot/linker.ld index 8570468..7911721 100644 --- a/kernel/src/arch/mipsel/boot/linker.ld +++ b/kernel/src/arch/mipsel/boot/linker.ld @@ -4,7 +4,7 @@ OUTPUT_ARCH(riscv) ENTRY(_start) -BASE_ADDRESS = 0x80100000; +BASE_ADDRESS = 0x80000000; SECTIONS { diff --git a/kernel/src/arch/mipsel/consts.rs b/kernel/src/arch/mipsel/consts.rs index ab7bf18..1bc6aa5 100644 --- a/kernel/src/arch/mipsel/consts.rs +++ b/kernel/src/arch/mipsel/consts.rs @@ -1,11 +1,11 @@ /// Platform specific constants +/// -pub const KERNEL_OFFSET: usize = 0x80100000; +pub use super::board::consts::*; -pub const KERNEL_HEAP_SIZE: usize = 0x00a0_0000; +pub const KERNEL_OFFSET: usize = 0x80000000; pub const MEMORY_OFFSET: usize = 0x8000_0000; -pub const MEMORY_END: usize = 0x8800_0000; pub const USER_STACK_OFFSET: usize = 0x80000000 - USER_STACK_SIZE; pub const USER_STACK_SIZE: usize = 0x10000; From 6e2947ac5678c7deca922fd3b2694b7c443a4ec5 Mon Sep 17 00:00:00 2001 From: Harry Chen Date: Sat, 6 Apr 2019 02:43:00 +0800 Subject: [PATCH 42/85] Fix uart address definition on thinpad Signed-off-by: Harry Chen --- kernel/src/arch/mipsel/board/thinpad/serial.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/kernel/src/arch/mipsel/board/thinpad/serial.rs b/kernel/src/arch/mipsel/board/thinpad/serial.rs index 95c693d..7407139 100644 --- a/kernel/src/arch/mipsel/board/thinpad/serial.rs +++ b/kernel/src/arch/mipsel/board/thinpad/serial.rs @@ -8,8 +8,8 @@ pub struct SerialPort { base: usize } -const UART_STATUS: usize = 0; -const UART_DATA: usize = 0; +const UART_STATUS: usize = 0x0; +const UART_DATA: usize = 0x4; const UART_STATUS_CTS: u8 = 0x1; // clear to send signal const UART_STATUS_DR: u8 = 0x2; // data ready signal From fb08410cb53a17f40078a828173f091ad8d598a6 Mon Sep 17 00:00:00 2001 From: Yuhao Zhou Date: Sat, 6 Apr 2019 02:46:40 +0800 Subject: [PATCH 43/85] Fix paging bug. --- kernel/src/arch/mipsel/boot/linker.ld | 2 +- kernel/src/arch/mipsel/interrupt.rs | 7 +++++++ kernel/src/arch/mipsel/paging.rs | 9 ++++++--- 3 files changed, 14 insertions(+), 4 deletions(-) diff --git a/kernel/src/arch/mipsel/boot/linker.ld b/kernel/src/arch/mipsel/boot/linker.ld index 7911721..0e4d0bb 100644 --- a/kernel/src/arch/mipsel/boot/linker.ld +++ b/kernel/src/arch/mipsel/boot/linker.ld @@ -15,9 +15,9 @@ SECTIONS .text : { stext = .; *(.text.entry) - *(.text .text.*) . = ALIGN(4K); *(.text.ebase) + *(.text .text.*) . = ALIGN(4K); etext = .; } diff --git a/kernel/src/arch/mipsel/interrupt.rs b/kernel/src/arch/mipsel/interrupt.rs index c87f223..abc0373 100644 --- a/kernel/src/arch/mipsel/interrupt.rs +++ b/kernel/src/arch/mipsel/interrupt.rs @@ -15,6 +15,7 @@ pub fn init() { unsafe { // Set the exception vector address cp0::ebase::write_u32(trap_entry as u32); + println!("Set ebase = {:x}", trap_entry as u32); let mut status = cp0::status::read(); // Enable IPI @@ -127,6 +128,10 @@ fn syscall(tf: &mut TrapFrame) { tf.v0 = ret as usize; } +extern { + static root_page_table_ptr : *mut usize; +} + fn page_fault(tf: &mut TrapFrame) { // TODO: set access/dirty bit let addr = tf.vaddr; @@ -135,4 +140,6 @@ fn page_fault(tf: &mut TrapFrame) { if !crate::memory::handle_page_fault(addr) { crate::trap::error(tf); } + + } diff --git a/kernel/src/arch/mipsel/paging.rs b/kernel/src/arch/mipsel/paging.rs index 3ea5a7a..772cea3 100644 --- a/kernel/src/arch/mipsel/paging.rs +++ b/kernel/src/arch/mipsel/paging.rs @@ -107,9 +107,12 @@ impl InactivePageTable for InactivePageTable0 { fn new_bare() -> Self { let target = alloc_frame().expect("failed to allocate frame"); let frame = Frame::of_addr(PhysAddr::new(target)); - active_table().with_temporary_map(target, |_, table: &mut MIPSPageTable| { - table.zero(); - }); + + let table = unsafe { + &mut *(target as *mut MIPSPageTable) + }; + + table.zero(); InactivePageTable0 { root_frame: frame } } From 9a9e8048cbd6e6d48e1278e94476045c056a6596 Mon Sep 17 00:00:00 2001 From: Yuhao Zhou Date: Sat, 6 Apr 2019 03:22:26 +0800 Subject: [PATCH 44/85] Move text base to higher location to avoid colliding with qemu BIOS --- kernel/src/arch/mipsel/boot/entry.S | 2 +- kernel/src/arch/mipsel/boot/linker.ld | 2 +- kernel/src/arch/mipsel/consts.rs | 2 +- kernel/src/fs/mod.rs | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/kernel/src/arch/mipsel/boot/entry.S b/kernel/src/arch/mipsel/boot/entry.S index 019006c..7be682d 100644 --- a/kernel/src/arch/mipsel/boot/entry.S +++ b/kernel/src/arch/mipsel/boot/entry.S @@ -22,7 +22,7 @@ _start: mtc0 t0, $12 # directly jump to main function - b rust_main + j rust_main nop .section .bss.stack diff --git a/kernel/src/arch/mipsel/boot/linker.ld b/kernel/src/arch/mipsel/boot/linker.ld index 0e4d0bb..420430d 100644 --- a/kernel/src/arch/mipsel/boot/linker.ld +++ b/kernel/src/arch/mipsel/boot/linker.ld @@ -4,7 +4,7 @@ OUTPUT_ARCH(riscv) ENTRY(_start) -BASE_ADDRESS = 0x80000000; +BASE_ADDRESS = 0x80100000; SECTIONS { diff --git a/kernel/src/arch/mipsel/consts.rs b/kernel/src/arch/mipsel/consts.rs index 1bc6aa5..a008f2e 100644 --- a/kernel/src/arch/mipsel/consts.rs +++ b/kernel/src/arch/mipsel/consts.rs @@ -3,7 +3,7 @@ pub use super::board::consts::*; -pub const KERNEL_OFFSET: usize = 0x80000000; +pub const KERNEL_OFFSET: usize = 0x80100000; pub const MEMORY_OFFSET: usize = 0x8000_0000; diff --git a/kernel/src/fs/mod.rs b/kernel/src/fs/mod.rs index 9414c47..dd5c6da 100644 --- a/kernel/src/fs/mod.rs +++ b/kernel/src/fs/mod.rs @@ -54,9 +54,9 @@ lazy_static! { fn _user_img_start(); fn _user_img_end(); } + println!("Sfs start {:x}, end {:x}", _user_img_start as usize, _user_img_end as usize); Arc::new(unsafe { device::MemBuf::new(_user_img_start, _user_img_end) }) }; - let sfs = SimpleFileSystem::open(device).expect("failed to open SFS"); sfs.root_inode() }; From 6cc607e0c8a4746f44c77c06147d84d7ead15c35 Mon Sep 17 00:00:00 2001 From: Harry Chen Date: Sat, 6 Apr 2019 11:20:50 +0800 Subject: [PATCH 45/85] Make aarch64 and mipsel use img instead of qcow Signed-off-by: Harry Chen --- kernel/Makefile | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/kernel/Makefile b/kernel/Makefile index ec9f892..ec23b36 100644 --- a/kernel/Makefile +++ b/kernel/Makefile @@ -51,11 +51,16 @@ user_dir := ../user ### export environments ### + +ifeq ($(arch), $(filter $(arch), aarch64 mipsel)) +#link user img, so use original image +export SFSIMG = $(user_dir)/build/$(arch).img +else export SFSIMG = $(user_dir)/build/$(arch).qcow2 +endif ifeq ($(arch), aarch64) board := raspi3 -export SFSIMG = $(user_dir)/build/$(arch).img endif # currently only mipsel architecture needs DTB linked to the kernel @@ -294,7 +299,6 @@ else ifeq ($(arch), aarch64) @$(objcopy) $(bootloader) --strip-all -O binary $@ else ifeq ($(arch), mipsel) # qemu-system-mipsel accepts ELF file only, so don't use objcopy - @cp $(kernel) $(kernel)_orig @$(strip) $(kernel) -o $@ endif From 603800457645e2615f0ff672184cbf7a19beb148 Mon Sep 17 00:00:00 2001 From: Yuhao Zhou Date: Sat, 6 Apr 2019 11:59:22 +0800 Subject: [PATCH 46/85] Add page table lookup in pagefault. --- kernel/src/arch/mipsel/interrupt.rs | 10 +++++++++- kernel/src/fs/mod.rs | 17 ++++++++++++++++- 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/kernel/src/arch/mipsel/interrupt.rs b/kernel/src/arch/mipsel/interrupt.rs index abc0373..fc59fae 100644 --- a/kernel/src/arch/mipsel/interrupt.rs +++ b/kernel/src/arch/mipsel/interrupt.rs @@ -1,6 +1,9 @@ use mips::interrupts; +use mips::tlb; use mips::registers::cp0; use crate::drivers::DRIVERS; +use mips::paging::{PageTable as MIPSPageTable, PageTableEntry, PageTableFlags as EF, TwoLevelPageTable}; +use mips::addr::*; pub use self::context::*; use log::*; @@ -141,5 +144,10 @@ fn page_fault(tf: &mut TrapFrame) { crate::trap::error(tf); } - + let virt_addr = VirtAddr::new(addr); + let root_table = unsafe { + &mut *(root_page_table_ptr as *mut MIPSPageTable) + }; + let tlb_entry = root_table.lookup(addr); + tlb::write_tlb_random(tlb_entry); } diff --git a/kernel/src/fs/mod.rs b/kernel/src/fs/mod.rs index dd5c6da..a045552 100644 --- a/kernel/src/fs/mod.rs +++ b/kernel/src/fs/mod.rs @@ -21,7 +21,7 @@ mod stdio; #[cfg(feature = "link_user")] global_asm!(concat!( r#" - .section .data + .section .data.img .global _user_img_start .global _user_img_end _user_img_start: @@ -57,7 +57,22 @@ lazy_static! { println!("Sfs start {:x}, end {:x}", _user_img_start as usize, _user_img_end as usize); Arc::new(unsafe { device::MemBuf::new(_user_img_start, _user_img_end) }) }; + + let device2 = { + extern { + fn _user_img_start(); + fn _user_img_end(); + } + Arc::new(unsafe { device::MemBuf::new(_user_img_start, _user_img_end) }) + }; + + let super_block = SimpleFileSystem::read(device2); + println!("Superblock: magic = {:x}, freemap_blocks = {:x}", super_block.magic, super_block.freemap_blocks); + println!("blocks = {:}", super_block.blocks); + println!("unused_blocks = {:}", super_block.unused_blocks); + let sfs = SimpleFileSystem::open(device).expect("failed to open SFS"); + // println!("{:}", sfs.free_map.read()); sfs.root_inode() }; } From b75e388aa1fdfde33a3b356bc3c3b958b2014461 Mon Sep 17 00:00:00 2001 From: Harry Chen Date: Sat, 6 Apr 2019 14:15:55 +0800 Subject: [PATCH 47/85] Fix backtrace for mipsel Signed-off-by: Harry Chen --- kernel/src/arch/mipsel/boot/entry.S | 2 +- kernel/src/backtrace.rs | 76 ++++++++++++++++++++++++++--- 2 files changed, 69 insertions(+), 9 deletions(-) diff --git a/kernel/src/arch/mipsel/boot/entry.S b/kernel/src/arch/mipsel/boot/entry.S index 7be682d..1a2a44b 100644 --- a/kernel/src/arch/mipsel/boot/entry.S +++ b/kernel/src/arch/mipsel/boot/entry.S @@ -22,7 +22,7 @@ _start: mtc0 t0, $12 # directly jump to main function - j rust_main + jal rust_main nop .section .bss.stack diff --git a/kernel/src/backtrace.rs b/kernel/src/backtrace.rs index af1b045..337cfc8 100644 --- a/kernel/src/backtrace.rs +++ b/kernel/src/backtrace.rs @@ -24,8 +24,8 @@ pub fn fp() -> usize { } #[cfg(any(target_arch = "mips"))] unsafe { - // fp = $30 - asm!("ori $0, $$30, 0" : "=r"(ptr)); + // read $sp + asm!("ori $0, $$29, 0" : "=r"(ptr)); } ptr @@ -57,22 +57,46 @@ pub fn lr() -> usize { ptr } + // Print the backtrace starting from the caller pub fn backtrace() { unsafe { let mut current_pc = lr(); let mut current_fp = fp(); let mut stack_num = 0; + + // adjust sp to the top address of backtrace() function + #[cfg(target_arch = "mips")] + { + let func_base = backtrace as *const isize; + let sp_offset = (*func_base << 16) >> 16; + current_fp = ((current_fp as isize) - sp_offset) as usize; + } + while current_pc >= stext as usize && current_pc <= etext as usize && current_fp as usize != 0 { - println!( - "#{} {:#018X} fp {:#018X}", - stack_num, - current_pc - size_of::(), - current_fp - ); + // print current backtrace + match size_of::() { + 4 => { + println!( + "Stack #{:02} PC: {:#010X} FP: {:#010X}", + stack_num, + current_pc - size_of::(), + current_fp + ); + }, + _ => { + println!( + "Stack #{:02} PC: {:#018X} FP: {:#018X}", + stack_num, + current_pc - size_of::(), + current_fp + ); + } + } + stack_num = stack_num + 1; #[cfg(any(target_arch = "riscv32", target_arch = "riscv64"))] { @@ -86,6 +110,42 @@ pub fn backtrace() { current_pc = *(current_fp as *const usize).offset(1); } } + #[cfg(target_arch = "mips")] + { + // the prologue of function is always like: + // main+0: 27bd____ addiu sp, sp, -____ + // main+4: afbf____ sw ra, ____(sp) + let mut code_ptr = current_pc as *const isize; + code_ptr = code_ptr.offset(-1); + + // get the stack size of last function + while (*code_ptr as usize >> 16) != 0x27bd { + code_ptr = code_ptr.offset(-1); + } + let sp_offset = (*code_ptr << 16) >> 16; + trace!("Found addiu sp @ {:08X}({:08x}) with sp offset {}", code_ptr as usize, *code_ptr, sp_offset); + + // get the return address offset of last function + let mut last_fun_found = false; + while (code_ptr as usize) < current_pc { + if (*code_ptr as usize >> 16) == 0xafbf { + last_fun_found = true; + break; + } + code_ptr = code_ptr.offset(1); + } + if last_fun_found { + // unwind stack + let ra_offset = (*code_ptr << 16) >> 16; + trace!("Found sw ra @ {:08X}({:08x}) with ra offset {}", code_ptr as usize, *code_ptr, ra_offset); + current_pc = *(((current_fp as isize) + ra_offset) as *const usize); + current_fp = ((current_fp as isize) - sp_offset) as usize; + trace!("New PC {:08X} FP {:08X}", current_pc, current_fp); + continue; + } else { + break; + } + } #[cfg(target_arch = "x86_64")] { // Kernel stack at 0x0000_57ac_0000_0000 (defined in bootloader crate) From 48864bd79b63fa9dee195b3540a3da69d2433975 Mon Sep 17 00:00:00 2001 From: Harry Chen Date: Sat, 6 Apr 2019 14:43:10 +0800 Subject: [PATCH 48/85] Add more output to backtrace, revert fs change, update rust-mips Signed-off-by: Harry Chen --- kernel/Cargo.lock | 2 +- kernel/Makefile | 2 +- kernel/src/backtrace.rs | 8 ++++++-- kernel/src/fs/mod.rs | 8 +------- 4 files changed, 9 insertions(+), 11 deletions(-) diff --git a/kernel/Cargo.lock b/kernel/Cargo.lock index 15929e7..a98db90 100644 --- a/kernel/Cargo.lock +++ b/kernel/Cargo.lock @@ -230,7 +230,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "mips" version = "0.1.0" -source = "git+https://github.com/Harry-Chen/rust-mips#8b8cbacb08aaaef93837d46599ce21759ef481de" +source = "git+https://github.com/Harry-Chen/rust-mips#ec0c31e18a904536ffa19bbd1f5d0d0fd19b2cd1" dependencies = [ "bit_field 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/kernel/Makefile b/kernel/Makefile index ec23b36..31ff5eb 100644 --- a/kernel/Makefile +++ b/kernel/Makefile @@ -298,7 +298,7 @@ else ifeq ($(arch), riscv64) else ifeq ($(arch), aarch64) @$(objcopy) $(bootloader) --strip-all -O binary $@ else ifeq ($(arch), mipsel) - # qemu-system-mipsel accepts ELF file only, so don't use objcopy +# qemu-system-mipsel accepts ELF file only, so objcopy is not needed @$(strip) $(kernel) -o $@ endif diff --git a/kernel/src/backtrace.rs b/kernel/src/backtrace.rs index 337cfc8..4262d53 100644 --- a/kernel/src/backtrace.rs +++ b/kernel/src/backtrace.rs @@ -73,6 +73,8 @@ pub fn backtrace() { current_fp = ((current_fp as isize) - sp_offset) as usize; } + println!("=== BEGIN rCore stack trace ==="); + while current_pc >= stext as usize && current_pc <= etext as usize && current_fp as usize != 0 @@ -81,7 +83,7 @@ pub fn backtrace() { match size_of::() { 4 => { println!( - "Stack #{:02} PC: {:#010X} FP: {:#010X}", + "#{:02} PC: {:#010X} FP: {:#010X}", stack_num, current_pc - size_of::(), current_fp @@ -89,7 +91,7 @@ pub fn backtrace() { }, _ => { println!( - "Stack #{:02} PC: {:#018X} FP: {:#018X}", + "#{:02} PC: {:#018X} FP: {:#018X}", stack_num, current_pc - size_of::(), current_fp @@ -143,6 +145,7 @@ pub fn backtrace() { trace!("New PC {:08X} FP {:08X}", current_pc, current_fp); continue; } else { + trace!("No sw ra found, probably due to optimizations."); break; } } @@ -159,5 +162,6 @@ pub fn backtrace() { current_pc = *(current_fp as *const usize).offset(1); } } + println!("=== END rCore stack trace ==="); } } diff --git a/kernel/src/fs/mod.rs b/kernel/src/fs/mod.rs index a045552..51e3298 100644 --- a/kernel/src/fs/mod.rs +++ b/kernel/src/fs/mod.rs @@ -54,7 +54,7 @@ lazy_static! { fn _user_img_start(); fn _user_img_end(); } - println!("Sfs start {:x}, end {:x}", _user_img_start as usize, _user_img_end as usize); + info!("SFS linked to kernel, from {:08x} to {:08x}", _user_img_start as usize, _user_img_end as usize); Arc::new(unsafe { device::MemBuf::new(_user_img_start, _user_img_end) }) }; @@ -66,13 +66,7 @@ lazy_static! { Arc::new(unsafe { device::MemBuf::new(_user_img_start, _user_img_end) }) }; - let super_block = SimpleFileSystem::read(device2); - println!("Superblock: magic = {:x}, freemap_blocks = {:x}", super_block.magic, super_block.freemap_blocks); - println!("blocks = {:}", super_block.blocks); - println!("unused_blocks = {:}", super_block.unused_blocks); - let sfs = SimpleFileSystem::open(device).expect("failed to open SFS"); - // println!("{:}", sfs.free_map.read()); sfs.root_inode() }; } From 62fe4e53611939d827a3a25d9ecb226965dc4501 Mon Sep 17 00:00:00 2001 From: Harry Chen Date: Sat, 6 Apr 2019 14:45:28 +0800 Subject: [PATCH 49/85] Update rust-mips crate Signed-off-by: Harry Chen --- kernel/Cargo.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/Cargo.lock b/kernel/Cargo.lock index a98db90..00aeaa9 100644 --- a/kernel/Cargo.lock +++ b/kernel/Cargo.lock @@ -230,7 +230,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "mips" version = "0.1.0" -source = "git+https://github.com/Harry-Chen/rust-mips#ec0c31e18a904536ffa19bbd1f5d0d0fd19b2cd1" +source = "git+https://github.com/Harry-Chen/rust-mips#ff6065e8397cda9872a1f42ec7bf0fcbb85bb253" dependencies = [ "bit_field 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", From fedb53346a9ffa5ad7e800aa3b9e1233834b510e Mon Sep 17 00:00:00 2001 From: Harry Chen Date: Sat, 6 Apr 2019 15:46:08 +0800 Subject: [PATCH 50/85] Update mips crate Signed-off-by: Harry Chen --- kernel/Cargo.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/Cargo.lock b/kernel/Cargo.lock index 00aeaa9..1ea185d 100644 --- a/kernel/Cargo.lock +++ b/kernel/Cargo.lock @@ -230,7 +230,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "mips" version = "0.1.0" -source = "git+https://github.com/Harry-Chen/rust-mips#ff6065e8397cda9872a1f42ec7bf0fcbb85bb253" +source = "git+https://github.com/Harry-Chen/rust-mips#e2cea12fc88f1f5a788a155972cd4047e7ad2b4f" dependencies = [ "bit_field 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", From bb374ba4bd19584bfa35affe0415111d41ef1309 Mon Sep 17 00:00:00 2001 From: Harry Chen Date: Sat, 6 Apr 2019 17:17:20 +0800 Subject: [PATCH 51/85] Mock a Mutex for serial on thinpad Signed-off-by: Harry Chen --- .../src/arch/mipsel/board/thinpad/serial.rs | 20 +++++++++---------- kernel/src/arch/mipsel/mod.rs | 2 +- 2 files changed, 10 insertions(+), 12 deletions(-) diff --git a/kernel/src/arch/mipsel/board/thinpad/serial.rs b/kernel/src/arch/mipsel/board/thinpad/serial.rs index 7407139..ed7bd73 100644 --- a/kernel/src/arch/mipsel/board/thinpad/serial.rs +++ b/kernel/src/arch/mipsel/board/thinpad/serial.rs @@ -2,8 +2,8 @@ use core::fmt::{Write, Result, Arguments}; use core::ptr::{read_volatile, write_volatile}; -use spin::Mutex; +#[derive(Debug, Clone, Copy)] pub struct SerialPort { base: usize } @@ -14,13 +14,7 @@ const UART_DATA: usize = 0x4; const UART_STATUS_CTS: u8 = 0x1; // clear to send signal const UART_STATUS_DR: u8 = 0x2; // data ready signal - impl SerialPort { - fn new() -> SerialPort { - SerialPort { - base: 0 - } - } pub fn init(&mut self, base: usize) { self.base = base; @@ -57,6 +51,11 @@ impl SerialPort { self.write_fmt(fmt).unwrap(); } + pub fn lock(&self) -> SerialPort { + self.clone() + } + + pub fn force_unlock(&self) {} } impl Write for SerialPort { @@ -84,10 +83,9 @@ fn read(addr: usize) -> T { unsafe { read_volatile(cell) } } - -lazy_static! { - pub static ref SERIAL_PORT: Mutex = Mutex::new(SerialPort::new()); -} +pub static SERIAL_PORT: SerialPort = SerialPort { + base: 0 +}; pub fn init(base: usize) { SERIAL_PORT.lock().init(base); diff --git a/kernel/src/arch/mipsel/mod.rs b/kernel/src/arch/mipsel/mod.rs index e4d78b0..3c7ebaa 100644 --- a/kernel/src/arch/mipsel/mod.rs +++ b/kernel/src/arch/mipsel/mod.rs @@ -42,7 +42,7 @@ pub extern fn rust_main() -> ! { // while unsafe { !cpu::has_started(hartid) } { } // println!("Hello RISCV! in hart {}, dtb @ {:#x}", hartid, dtb); // others_main(); - loop {} + // loop {} } unsafe { memory::clear_bss(); } From 1f8b73744c96ddef86b37b7e04ac2e4b1f6bdf56 Mon Sep 17 00:00:00 2001 From: Yuhao Zhou Date: Sat, 6 Apr 2019 19:26:14 +0800 Subject: [PATCH 52/85] Disable multi-CPU. --- kernel/src/arch/mipsel/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/src/arch/mipsel/mod.rs b/kernel/src/arch/mipsel/mod.rs index 3c7ebaa..e4d78b0 100644 --- a/kernel/src/arch/mipsel/mod.rs +++ b/kernel/src/arch/mipsel/mod.rs @@ -42,7 +42,7 @@ pub extern fn rust_main() -> ! { // while unsafe { !cpu::has_started(hartid) } { } // println!("Hello RISCV! in hart {}, dtb @ {:#x}", hartid, dtb); // others_main(); - // loop {} + loop {} } unsafe { memory::clear_bss(); } From 5e44304f740c4d745ff01a029592bb01eda29b8e Mon Sep 17 00:00:00 2001 From: Yuhao Zhou Date: Sat, 6 Apr 2019 20:26:10 +0800 Subject: [PATCH 53/85] Fix root page table ptr/buffer. --- kernel/src/arch/mipsel/boot/context.S | 4 +-- kernel/src/arch/mipsel/boot/trap.S | 8 +++--- kernel/src/arch/mipsel/context.rs | 4 --- kernel/src/arch/mipsel/interrupt.rs | 7 ++---- kernel/src/arch/mipsel/memory.rs | 9 +++++++ kernel/src/arch/mipsel/paging.rs | 36 ++++++++++++++++++++------- 6 files changed, 44 insertions(+), 24 deletions(-) diff --git a/kernel/src/arch/mipsel/boot/context.S b/kernel/src/arch/mipsel/boot/context.S index 86c9a85..6a3975a 100644 --- a/kernel/src/arch/mipsel/boot/context.S +++ b/kernel/src/arch/mipsel/boot/context.S @@ -5,7 +5,7 @@ .section .text.context .globl switch_context -.extern root_page_table_ptr +.extern _root_page_table_ptr switch_context: // save from's registers @@ -25,7 +25,7 @@ switch_context: sw ra, 12*4(sp) sw sp, 13*4(sp) - la s0, root_page_table_ptr + la s0, _root_page_table_ptr lw AT, 0(s0) sw AT, 4(sp) diff --git a/kernel/src/arch/mipsel/boot/trap.S b/kernel/src/arch/mipsel/boot/trap.S index 513b9cd..04cf983 100644 --- a/kernel/src/arch/mipsel/boot/trap.S +++ b/kernel/src/arch/mipsel/boot/trap.S @@ -158,9 +158,9 @@ kernel_stack: kernel_stack_top: .align 12 #PGSHIFT - .global root_page_table_buffer -root_page_table_buffer: + .global _root_page_table_buffer +_root_page_table_buffer: .space 1024 * 4 # 4KB - .global root_page_table_ptr -root_page_table_ptr: + .global _root_page_table_ptr +_root_page_table_ptr: .space 4 # 4bytes diff --git a/kernel/src/arch/mipsel/context.rs b/kernel/src/arch/mipsel/context.rs index 372a186..4d20869 100644 --- a/kernel/src/arch/mipsel/context.rs +++ b/kernel/src/arch/mipsel/context.rs @@ -1,9 +1,5 @@ use mips::registers::cp0; -extern { - static root_page_table_ptr : *mut usize; -} - /// Saved registers on a trap. #[derive(Clone)] #[repr(C)] diff --git a/kernel/src/arch/mipsel/interrupt.rs b/kernel/src/arch/mipsel/interrupt.rs index fc59fae..bf6256b 100644 --- a/kernel/src/arch/mipsel/interrupt.rs +++ b/kernel/src/arch/mipsel/interrupt.rs @@ -5,6 +5,7 @@ use crate::drivers::DRIVERS; use mips::paging::{PageTable as MIPSPageTable, PageTableEntry, PageTableFlags as EF, TwoLevelPageTable}; use mips::addr::*; pub use self::context::*; +use crate::arch::paging::get_root_page_table_ptr; use log::*; #[path = "context.rs"] @@ -131,10 +132,6 @@ fn syscall(tf: &mut TrapFrame) { tf.v0 = ret as usize; } -extern { - static root_page_table_ptr : *mut usize; -} - fn page_fault(tf: &mut TrapFrame) { // TODO: set access/dirty bit let addr = tf.vaddr; @@ -146,7 +143,7 @@ fn page_fault(tf: &mut TrapFrame) { let virt_addr = VirtAddr::new(addr); let root_table = unsafe { - &mut *(root_page_table_ptr as *mut MIPSPageTable) + &mut *(get_root_page_table_ptr() as *mut MIPSPageTable) }; let tlb_entry = root_table.lookup(addr); tlb::write_tlb_random(tlb_entry); diff --git a/kernel/src/arch/mipsel/memory.rs b/kernel/src/arch/mipsel/memory.rs index a1f09f9..67ff901 100644 --- a/kernel/src/arch/mipsel/memory.rs +++ b/kernel/src/arch/mipsel/memory.rs @@ -3,12 +3,21 @@ use rcore_memory::PAGE_SIZE; use log::*; use crate::memory::{FRAME_ALLOCATOR, init_heap, MemoryAttr, MemorySet, Linear}; use crate::consts::{MEMORY_OFFSET, MEMORY_END, KERNEL_OFFSET}; +use crate::arch::paging::*; /// Initialize the memory management module pub fn init() { // initialize heap and Frame allocator init_frame_allocator(); init_heap(); + + set_root_page_table_ptr(0xFFFF_FFFF); + extern "C" { + fn _root_page_table_buffer(); + fn _root_page_table_ptr(); + } + + println!("_root_page_table_ptr {:x}", _root_page_table_ptr as usize); } pub fn init_other() { diff --git a/kernel/src/arch/mipsel/paging.rs b/kernel/src/arch/mipsel/paging.rs index 772cea3..47c2899 100644 --- a/kernel/src/arch/mipsel/paging.rs +++ b/kernel/src/arch/mipsel/paging.rs @@ -6,8 +6,6 @@ use mips::paging::{Mapper, PageTable as MIPSPageTable, PageTableEntry, PageTable use mips::paging::{FrameAllocator, FrameDeallocator}; use rcore_memory::paging::*; use log::*; -#[cfg(target_arch = "riscv32")] -use crate::consts::KERNEL_P2_INDEX; pub struct ActivePageTable(TwoLevelPageTable<'static>, PageEntry); @@ -46,18 +44,38 @@ impl PageTable for ActivePageTable { } } +extern "C" { + fn _root_page_table_buffer(); + fn _root_page_table_ptr(); +} + +pub fn set_root_page_table_ptr(ptr : usize) { + unsafe { + *(_root_page_table_ptr as *mut usize) = ptr; + } +} + +pub fn get_root_page_table_ptr() -> usize { + unsafe { + *(_root_page_table_ptr as *mut usize) + } +} + +pub fn root_page_table_buffer() -> &'static mut MIPSPageTable { + unsafe { + &mut *(_root_page_table_ptr as *mut MIPSPageTable) + } +} + + impl PageTableExt for ActivePageTable {} /// The virtual address of root page table -extern { - static root_page_table_buffer : *mut MIPSPageTable; - static root_page_table_ptr : *mut usize; -} impl ActivePageTable { pub unsafe fn new() -> Self { ActivePageTable( - TwoLevelPageTable::new(&mut *(root_page_table_buffer as *mut MIPSPageTable)), + TwoLevelPageTable::new(root_page_table_buffer()), ::core::mem::uninitialized() ) } @@ -123,11 +141,11 @@ impl InactivePageTable for InactivePageTable0 { } unsafe fn set_token(token: usize) { - *root_page_table_ptr = token; + set_root_page_table_ptr(token); } fn active_token() -> usize { - unsafe { *root_page_table_ptr } + get_root_page_table_ptr() } fn flush_tlb() { From 3d083eec0c9be1cc5189ba1fba301b59845449e3 Mon Sep 17 00:00:00 2001 From: Yuhao Zhou Date: Sat, 6 Apr 2019 21:08:36 +0800 Subject: [PATCH 54/85] Fix pgfault handler. --- kernel/src/arch/mipsel/interrupt.rs | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/kernel/src/arch/mipsel/interrupt.rs b/kernel/src/arch/mipsel/interrupt.rs index bf6256b..249fd94 100644 --- a/kernel/src/arch/mipsel/interrupt.rs +++ b/kernel/src/arch/mipsel/interrupt.rs @@ -137,14 +137,15 @@ fn page_fault(tf: &mut TrapFrame) { let addr = tf.vaddr; trace!("\nEXCEPTION: Page Fault @ {:#x}", addr); - if !crate::memory::handle_page_fault(addr) { - crate::trap::error(tf); - } - let virt_addr = VirtAddr::new(addr); let root_table = unsafe { &mut *(get_root_page_table_ptr() as *mut MIPSPageTable) }; - let tlb_entry = root_table.lookup(addr); - tlb::write_tlb_random(tlb_entry); + let tlb_result = root_table.lookup(addr); + match tlb_result { + Ok(tlb_entry) => tlb::write_tlb_random(tlb_entry), + Err(()) => if !crate::memory::handle_page_fault(addr) { + crate::trap::error(tf); + } + } } From a2e98d73fd9dcfdf93c544e3bab42e461cbb9986 Mon Sep 17 00:00:00 2001 From: Harry Chen Date: Sat, 6 Apr 2019 21:59:16 +0800 Subject: [PATCH 55/85] Extract serial driver and add mipssim board for mipsel Signed-off-by: Harry Chen --- kernel/Cargo.lock | 2 +- kernel/Cargo.toml | 3 +- kernel/Makefile | 7 +++- kernel/src/arch/mipsel/board/malta/consts.rs | 2 +- kernel/src/arch/mipsel/board/malta/mod.rs | 3 +- .../src/arch/mipsel/board/mipssim/consts.rs | 3 ++ .../src/arch/mipsel/board/mipssim/device.dts | 36 +++++++++++++++++++ kernel/src/arch/mipsel/board/mipssim/mod.rs | 27 ++++++++++++++ .../src/arch/mipsel/board/thinpad/consts.rs | 2 +- kernel/src/arch/mipsel/board/thinpad/mod.rs | 1 + kernel/src/arch/mipsel/mod.rs | 5 +++ .../serial.rs => drivers/serial/16550_reg.rs} | 0 .../serial/simple_uart.rs} | 0 13 files changed, 85 insertions(+), 6 deletions(-) create mode 100644 kernel/src/arch/mipsel/board/mipssim/consts.rs create mode 100644 kernel/src/arch/mipsel/board/mipssim/device.dts create mode 100644 kernel/src/arch/mipsel/board/mipssim/mod.rs rename kernel/src/{arch/mipsel/board/malta/serial.rs => drivers/serial/16550_reg.rs} (100%) rename kernel/src/{arch/mipsel/board/thinpad/serial.rs => drivers/serial/simple_uart.rs} (100%) diff --git a/kernel/Cargo.lock b/kernel/Cargo.lock index 1ea185d..702c095 100644 --- a/kernel/Cargo.lock +++ b/kernel/Cargo.lock @@ -230,7 +230,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "mips" version = "0.1.0" -source = "git+https://github.com/Harry-Chen/rust-mips#e2cea12fc88f1f5a788a155972cd4047e7ad2b4f" +source = "git+https://github.com/Harry-Chen/rust-mips#bee9865920bceef12dbb527c1c237de905129c0b" dependencies = [ "bit_field 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/kernel/Cargo.toml b/kernel/Cargo.toml index 2ce9880..74ab119 100644 --- a/kernel/Cargo.toml +++ b/kernel/Cargo.toml @@ -26,8 +26,9 @@ board_u540 = ["sv39", "link_user"] nographic = [] board_raspi3 = ["bcm2837", "link_user"] raspi3_use_generic_timer = ["bcm2837/use_generic_timer"] -# for mipsel qemu malta machine +# for qemu machine board_malta = ["link_user"] +board_mipssim = ["link_user"] # for thinpad board_thinpad = ["link_user"] # Hard link user program diff --git a/kernel/Makefile b/kernel/Makefile index 31ff5eb..8d7fc9e 100644 --- a/kernel/Makefile +++ b/kernel/Makefile @@ -68,6 +68,11 @@ ifeq ($(arch), mipsel) dtb := src/arch/$(arch)/board/$(board)/device.dtb endif +# mipssim does not support SMP +ifeq ($(board), mipssim) +smp := 1 +endif + export ARCH = $(arch) export BOARD = $(board) export SMP = $(smp) @@ -129,7 +134,7 @@ qemu_opts += \ -kernel $(kernel_img) else ifeq ($(arch), mipsel) -ifeq ($(board), malta) +ifeq ($(board), $(filter $(board), malta mipssim)) qemu_opts += \ -machine $(board) \ -serial mon:stdio \ diff --git a/kernel/src/arch/mipsel/board/malta/consts.rs b/kernel/src/arch/mipsel/board/malta/consts.rs index 5f1f8f5..73ff966 100644 --- a/kernel/src/arch/mipsel/board/malta/consts.rs +++ b/kernel/src/arch/mipsel/board/malta/consts.rs @@ -1,3 +1,3 @@ -/// board specific constants for malta +/// board specific constants pub const MEMORY_END: usize = 0x8800_0000; pub const KERNEL_HEAP_SIZE: usize = 0x00a0_0000; diff --git a/kernel/src/arch/mipsel/board/malta/mod.rs b/kernel/src/arch/mipsel/board/malta/mod.rs index 05b27b7..0c594ef 100644 --- a/kernel/src/arch/mipsel/board/malta/mod.rs +++ b/kernel/src/arch/mipsel/board/malta/mod.rs @@ -1,6 +1,7 @@ use once::*; use alloc::string::String; +#[path = "../../../../drivers/serial/16550_reg.rs"] pub mod serial; #[path = "../../../../drivers/gpu/fb.rs"] pub mod fb; @@ -21,6 +22,6 @@ pub fn init_driver() { // timer::init(); } -pub fn probe_fb_info(width: u32, height: u32, depth: u32) -> Result<(fb::FramebufferInfo, usize), String> { +pub fn probe_fb_info(_width: u32, _height: u32, _depth: u32) -> Result<(fb::FramebufferInfo, usize), String> { Err(String::from("Framebuffer not usable on malta board")) } \ No newline at end of file diff --git a/kernel/src/arch/mipsel/board/mipssim/consts.rs b/kernel/src/arch/mipsel/board/mipssim/consts.rs new file mode 100644 index 0000000..73ff966 --- /dev/null +++ b/kernel/src/arch/mipsel/board/mipssim/consts.rs @@ -0,0 +1,3 @@ +/// board specific constants +pub const MEMORY_END: usize = 0x8800_0000; +pub const KERNEL_HEAP_SIZE: usize = 0x00a0_0000; diff --git a/kernel/src/arch/mipsel/board/mipssim/device.dts b/kernel/src/arch/mipsel/board/mipssim/device.dts new file mode 100644 index 0000000..2e99f7b --- /dev/null +++ b/kernel/src/arch/mipsel/board/mipssim/device.dts @@ -0,0 +1,36 @@ +/dts-v1/; + + +/ { + model = "qemu mipssim"; + compatible = "qemu,mipssim"; + #address-cells = <1>; + #size-cells = <1>; + + chosen { + stdio = &uart0; + }; + + aliases { }; + + cpu_intc: interrupt-controller { + compatible = "mti,cpu-interrupt-controller"; + interrupt-controller; + #interrupt-cells = <1>; + }; + + main_memory: memory@0 { + device_type = "memory"; + reg = <0x00000000 0x10000000>; + }; + + uart0: serial@bfd003f8 { + compatible = "ns16550a"; + reg = <0xbfd003f8 0x8>; + clock-frequency = <1843200>; + /* attached to the MIPS CPU INT2 pin, ie interrupt 4 */ + interrupt-parent = <&cpu_intc>; + interrupts = <4>; + }; + +}; diff --git a/kernel/src/arch/mipsel/board/mipssim/mod.rs b/kernel/src/arch/mipsel/board/mipssim/mod.rs new file mode 100644 index 0000000..6633d7d --- /dev/null +++ b/kernel/src/arch/mipsel/board/mipssim/mod.rs @@ -0,0 +1,27 @@ +use once::*; +use alloc::string::String; + +#[path = "../../../../drivers/serial/16550_reg.rs"] +pub mod serial; +#[path = "../../../../drivers/gpu/fb.rs"] +pub mod fb; +#[path = "../../../../drivers/console/mod.rs"] +pub mod console; +pub mod consts; + +/// Initialize serial port first +pub fn init_serial_early() { + assert_has_not_been_called!("board::init must be called only once"); + serial::init(0xbfd003f8); + println!("Hello QEMU MIPSSIM!"); +} + +/// Initialize other board drivers +pub fn init_driver() { + // TODO: add possibly more drivers + // timer::init(); +} + +pub fn probe_fb_info(_width: u32, _height: u32, _depth: u32) -> Result<(fb::FramebufferInfo, usize), String> { + Err(String::from("Framebuffer not usable on mipssim board")) +} \ No newline at end of file diff --git a/kernel/src/arch/mipsel/board/thinpad/consts.rs b/kernel/src/arch/mipsel/board/thinpad/consts.rs index 9a10cde..b59309a 100644 --- a/kernel/src/arch/mipsel/board/thinpad/consts.rs +++ b/kernel/src/arch/mipsel/board/thinpad/consts.rs @@ -1,3 +1,3 @@ -/// board specific constants for thinpad +/// board specific constants pub const MEMORY_END: usize = 0x8080_0000; pub const KERNEL_HEAP_SIZE: usize = 0x0020_0000; diff --git a/kernel/src/arch/mipsel/board/thinpad/mod.rs b/kernel/src/arch/mipsel/board/thinpad/mod.rs index 358197f..1ebf3d1 100644 --- a/kernel/src/arch/mipsel/board/thinpad/mod.rs +++ b/kernel/src/arch/mipsel/board/thinpad/mod.rs @@ -1,6 +1,7 @@ use once::*; use alloc::string::String; +#[path = "../../../../drivers/serial/simple_uart.rs"] pub mod serial; #[path = "../../../../drivers/gpu/fb.rs"] pub mod fb; diff --git a/kernel/src/arch/mipsel/mod.rs b/kernel/src/arch/mipsel/mod.rs index e4d78b0..6347d3c 100644 --- a/kernel/src/arch/mipsel/mod.rs +++ b/kernel/src/arch/mipsel/mod.rs @@ -22,6 +22,11 @@ pub mod board; #[path = "board/thinpad/mod.rs"] pub mod board; +#[cfg(feature = "board_mipssim")] +#[path = "board/mipssim/mod.rs"] +pub mod board; + + extern "C" { fn _dtb_start(); fn _dtb_end(); diff --git a/kernel/src/arch/mipsel/board/malta/serial.rs b/kernel/src/drivers/serial/16550_reg.rs similarity index 100% rename from kernel/src/arch/mipsel/board/malta/serial.rs rename to kernel/src/drivers/serial/16550_reg.rs diff --git a/kernel/src/arch/mipsel/board/thinpad/serial.rs b/kernel/src/drivers/serial/simple_uart.rs similarity index 100% rename from kernel/src/arch/mipsel/board/thinpad/serial.rs rename to kernel/src/drivers/serial/simple_uart.rs From fbc421ee4cbc4d0aa269a5041cc2cdea36702ad2 Mon Sep 17 00:00:00 2001 From: Yuhao Zhou Date: Sat, 6 Apr 2019 23:50:05 +0800 Subject: [PATCH 56/85] Fix trapframe size. --- kernel/src/arch/mipsel/boot/context.S | 6 ++---- kernel/src/arch/mipsel/context.rs | 2 ++ 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/kernel/src/arch/mipsel/boot/context.S b/kernel/src/arch/mipsel/boot/context.S index 6a3975a..b3c1e72 100644 --- a/kernel/src/arch/mipsel/boot/context.S +++ b/kernel/src/arch/mipsel/boot/context.S @@ -22,8 +22,8 @@ switch_context: sw s7, 9*4(sp) sw s8, 10*4(sp) sw gp, 11*4(sp) - sw ra, 12*4(sp) - sw sp, 13*4(sp) + // sw ra, 12*4(sp) + // sw sp, 13*4(sp) la s0, _root_page_table_ptr lw AT, 0(s0) @@ -45,8 +45,6 @@ switch_context: lw s7, 9*4(sp) lw s8, 10*4(sp) lw gp, 11*4(sp) - lw ra, 12*4(sp) - lw sp, 13*4(sp) addi sp, sp, (4*14) sw zero, 0(a1) diff --git a/kernel/src/arch/mipsel/context.rs b/kernel/src/arch/mipsel/context.rs index 4d20869..035969f 100644 --- a/kernel/src/arch/mipsel/context.rs +++ b/kernel/src/arch/mipsel/context.rs @@ -4,6 +4,8 @@ use mips::registers::cp0; #[derive(Clone)] #[repr(C)] pub struct TrapFrame { + /// unused 16 bytes + pub unused: [usize; 4], /// CP0 status register pub status: cp0::status::Status, /// CP0 cause register From bb123add188c4e20c638d8a5ca5ab5af30513100 Mon Sep 17 00:00:00 2001 From: Harry Chen Date: Sun, 7 Apr 2019 01:32:32 +0800 Subject: [PATCH 57/85] Eliminate multiple warnings, update user app repo Signed-off-by: Harry Chen --- kernel/src/arch/mipsel/mod.rs | 2 -- kernel/src/drivers/serial/16550_reg.rs | 2 ++ kernel/src/sync/mutex.rs | 4 ++-- user | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/kernel/src/arch/mipsel/mod.rs b/kernel/src/arch/mipsel/mod.rs index 6347d3c..9bc4c4e 100644 --- a/kernel/src/arch/mipsel/mod.rs +++ b/kernel/src/arch/mipsel/mod.rs @@ -12,7 +12,6 @@ pub mod driver; use log::*; use mips::registers::cp0; -use mips::instructions; #[cfg(feature = "board_malta")] #[path = "board/malta/mod.rs"] @@ -40,7 +39,6 @@ pub extern fn rust_main() -> ! { let ebase = cp0::ebase::read_u32(); let cpu_id = ebase & 0x3ff; let dtb_start = _dtb_start as usize; - let dtb_end = _dtb_end as usize; if cpu_id != BOOT_CPU_ID { // TODO: run others_main on other CPU diff --git a/kernel/src/drivers/serial/16550_reg.rs b/kernel/src/drivers/serial/16550_reg.rs index b624729..62330c4 100644 --- a/kernel/src/drivers/serial/16550_reg.rs +++ b/kernel/src/drivers/serial/16550_reg.rs @@ -1,5 +1,7 @@ //! 16550 serial adapter driver for malta board +#![allow(dead_code)] + use core::fmt::{Write, Result, Arguments}; use core::ptr::{read_volatile, write_volatile}; use spin::Mutex; diff --git a/kernel/src/sync/mutex.rs b/kernel/src/sync/mutex.rs index e319fde..8af1460 100644 --- a/kernel/src/sync/mutex.rs +++ b/kernel/src/sync/mutex.rs @@ -216,7 +216,7 @@ impl MutexSupport for Spin { unsafe { #[cfg(target_arch = "x86_64")] asm!("pause" :::: "volatile"); - #[cfg(any(target_arch = "riscv32", target_arch = "riscv64"))] + #[cfg(any(target_arch = "riscv32", target_arch = "riscv64", target_arch = "mips"))] asm!("nop" :::: "volatile"); #[cfg(target_arch = "aarch64")] asm!("yield" :::: "volatile"); @@ -254,7 +254,7 @@ impl MutexSupport for SpinNoIrq { unsafe { #[cfg(target_arch = "x86_64")] asm!("pause" :::: "volatile"); - #[cfg(any(target_arch = "riscv32", target_arch = "riscv64"))] + #[cfg(any(target_arch = "riscv32", target_arch = "riscv64", target_arch = "mips"))] asm!("nop" :::: "volatile"); #[cfg(target_arch = "aarch64")] asm!("yield" :::: "volatile"); diff --git a/user b/user index 67890ae..a460c5b 160000 --- a/user +++ b/user @@ -1 +1 @@ -Subproject commit 67890aeb4205083d5a95b1f70de92ae39b549c8c +Subproject commit a460c5b32744292ed50922a159fa22c830aa61b9 From f535073fbcc3b37153b9472c779cf75f447aa843 Mon Sep 17 00:00:00 2001 From: Yuhao Zhou Date: Sun, 7 Apr 2019 02:45:41 +0800 Subject: [PATCH 58/85] Support user thread. --- kernel/src/arch/mipsel/boot/trap.S | 3 ++- kernel/src/arch/mipsel/consts.rs | 2 +- kernel/src/arch/mipsel/context.rs | 4 ++++ kernel/src/arch/mipsel/interrupt.rs | 7 ++++--- kernel/src/arch/mipsel/timer.rs | 6 ++++-- kernel/src/fs/mod.rs | 8 -------- 6 files changed, 15 insertions(+), 15 deletions(-) diff --git a/kernel/src/arch/mipsel/boot/trap.S b/kernel/src/arch/mipsel/boot/trap.S index 04cf983..d232d33 100644 --- a/kernel/src/arch/mipsel/boot/trap.S +++ b/kernel/src/arch/mipsel/boot/trap.S @@ -92,8 +92,9 @@ trap_from_kernel: mtc0 t1, $12 # cp0.status # prepare to call rust_trap + ori a0, sp, 0 /* set argument (trapframe) */ jal rust_trap - addiu a0, sp, 16 /* set argument (trapframe) */ + nop .globl trap_return trap_return: diff --git a/kernel/src/arch/mipsel/consts.rs b/kernel/src/arch/mipsel/consts.rs index a008f2e..cf428ee 100644 --- a/kernel/src/arch/mipsel/consts.rs +++ b/kernel/src/arch/mipsel/consts.rs @@ -9,6 +9,6 @@ pub const MEMORY_OFFSET: usize = 0x8000_0000; pub const USER_STACK_OFFSET: usize = 0x80000000 - USER_STACK_SIZE; pub const USER_STACK_SIZE: usize = 0x10000; -pub const USER32_STACK_OFFSET: usize = 0xC0000000 - USER_STACK_SIZE; +pub const USER32_STACK_OFFSET: usize = 0x80000000 - USER_STACK_SIZE; pub const MAX_DTB_SIZE: usize = 0x2000; diff --git a/kernel/src/arch/mipsel/context.rs b/kernel/src/arch/mipsel/context.rs index 035969f..9227bef 100644 --- a/kernel/src/arch/mipsel/context.rs +++ b/kernel/src/arch/mipsel/context.rs @@ -174,6 +174,8 @@ impl Context { /// The stack pointer will be set to `kstack_top`. /// The SATP register will be set to `satp`. pub unsafe fn new_kernel_thread(entry: extern fn(usize) -> !, arg: usize, kstack_top: usize, satp: usize) -> Self { + trace!("New kernel thread @ {:x}, stack = {:x}", entry as usize, kstack_top); + InitStack { context: ContextData::new(satp), tf: TrapFrame::new_kernel_thread(entry, arg, kstack_top), @@ -186,6 +188,8 @@ impl Context { /// The stack pointer of user and kernel mode will be set to `ustack_top`, `kstack_top`. /// The SATP register will be set to `satp`. pub unsafe fn new_user_thread(entry_addr: usize, ustack_top: usize, kstack_top: usize, _is32: bool, satp: usize) -> Self { + trace!("New user thread @ {:x}, stack = {:x}", entry_addr, kstack_top); + InitStack { context: ContextData::new(satp), tf: TrapFrame::new_user_thread(entry_addr, ustack_top), diff --git a/kernel/src/arch/mipsel/interrupt.rs b/kernel/src/arch/mipsel/interrupt.rs index 249fd94..09b2c44 100644 --- a/kernel/src/arch/mipsel/interrupt.rs +++ b/kernel/src/arch/mipsel/interrupt.rs @@ -61,7 +61,7 @@ pub unsafe fn restore(flags: usize) { #[no_mangle] pub extern fn rust_trap(tf: &mut TrapFrame) { use cp0::cause::{Exception as E}; - trace!("Interrupt @ CPU{}: {:?} ", 0, tf.cause.cause()); + trace!("Exception @ CPU{}: {:?} ", 0, tf.cause.cause()); match tf.cause.cause() { E::Interrupt => interrupt_dispatcher(tf), E::Syscall => syscall(tf), @@ -75,6 +75,7 @@ pub extern fn rust_trap(tf: &mut TrapFrame) { fn interrupt_dispatcher(tf: &mut TrapFrame) { let pint = tf.cause.pending_interrupt(); + trace!(" Interrupt {:?} ", tf.cause.pending_interrupt()); if (pint & 0b10000_00) != 0 { timer(); } else if (pint & 0xb01111_00) != 0 { @@ -116,9 +117,9 @@ fn try_process_drivers() -> bool { } fn ipi() { - /* do nothing */ debug!("IPI"); -// super::sbi::clear_ipi(); + cp0::cause::reset_soft_int0(); + cp0::cause::reset_soft_int1(); } fn timer() { diff --git a/kernel/src/arch/mipsel/timer.rs b/kernel/src/arch/mipsel/timer.rs index 466c2d2..9659358 100644 --- a/kernel/src/arch/mipsel/timer.rs +++ b/kernel/src/arch/mipsel/timer.rs @@ -10,6 +10,7 @@ pub fn read_epoch() -> u64 { pub fn init() { // Enable supervisor timer interrupt cp0::status::enable_hard_int5(); // IP(7), timer interrupt + cp0::count::write_u32(0); set_next(); info!("timer: init end"); } @@ -18,6 +19,7 @@ pub fn init() { pub fn set_next() { // 100Hz @ QEMU let timebase = 250000; - cp0::count::write_u32(0); - cp0::compare::write_u32(timebase); + cp0::compare::write_u32( + cp0::count::read_u32() + timebase + ); } diff --git a/kernel/src/fs/mod.rs b/kernel/src/fs/mod.rs index 51e3298..1b772a9 100644 --- a/kernel/src/fs/mod.rs +++ b/kernel/src/fs/mod.rs @@ -58,14 +58,6 @@ lazy_static! { Arc::new(unsafe { device::MemBuf::new(_user_img_start, _user_img_end) }) }; - let device2 = { - extern { - fn _user_img_start(); - fn _user_img_end(); - } - Arc::new(unsafe { device::MemBuf::new(_user_img_start, _user_img_end) }) - }; - let sfs = SimpleFileSystem::open(device).expect("failed to open SFS"); sfs.root_inode() }; From da8d32c0cfc365b158586d5325a98c4af667e725 Mon Sep 17 00:00:00 2001 From: Yuhao Zhou Date: Sun, 7 Apr 2019 04:20:17 +0800 Subject: [PATCH 59/85] Update syscall convention. --- kernel/src/arch/mipsel/interrupt.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/kernel/src/arch/mipsel/interrupt.rs b/kernel/src/arch/mipsel/interrupt.rs index 09b2c44..f0b3128 100644 --- a/kernel/src/arch/mipsel/interrupt.rs +++ b/kernel/src/arch/mipsel/interrupt.rs @@ -76,9 +76,9 @@ pub extern fn rust_trap(tf: &mut TrapFrame) { fn interrupt_dispatcher(tf: &mut TrapFrame) { let pint = tf.cause.pending_interrupt(); trace!(" Interrupt {:?} ", tf.cause.pending_interrupt()); - if (pint & 0b10000_00) != 0 { + if (pint & 0b100_000_00) != 0 { timer(); - } else if (pint & 0xb01111_00) != 0 { + } else if (pint & 0b011_111_00) != 0 { external(); } else { ipi(); @@ -129,7 +129,7 @@ fn timer() { fn syscall(tf: &mut TrapFrame) { tf.epc += 4; // Must before syscall, because of fork. - let ret = crate::syscall::syscall(tf.t0, [tf.t0, tf.t1, tf.t2, tf.t3, tf.s0, tf.s1], tf); + let ret = crate::syscall::syscall(tf.t0, [tf.a0, tf.a1, tf.a2, tf.a3, tf.s0, tf.s1], tf); tf.v0 = ret as usize; } From 9d576b482720fc093dacbac52003f250f9be6382 Mon Sep 17 00:00:00 2001 From: Yuhao Zhou Date: Sun, 7 Apr 2019 04:21:35 +0800 Subject: [PATCH 60/85] Update Cargo.lock for rust-mips. --- kernel/Cargo.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/Cargo.lock b/kernel/Cargo.lock index 702c095..d1bd1be 100644 --- a/kernel/Cargo.lock +++ b/kernel/Cargo.lock @@ -230,7 +230,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "mips" version = "0.1.0" -source = "git+https://github.com/Harry-Chen/rust-mips#bee9865920bceef12dbb527c1c237de905129c0b" +source = "git+https://github.com/Harry-Chen/rust-mips#1f3df9589869670621baa863b87a3444d80f08a6" dependencies = [ "bit_field 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", From a0f298f6ddee172f4fc6c289d0c8dfdb1ea85280 Mon Sep 17 00:00:00 2001 From: Harry Chen Date: Sun, 7 Apr 2019 16:21:15 +0800 Subject: [PATCH 61/85] Use MIPS N32 abi for syscall handling Signed-off-by: Harry Chen --- kernel/src/arch/mipsel/interrupt.rs | 13 +++++++++++-- user | 2 +- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/kernel/src/arch/mipsel/interrupt.rs b/kernel/src/arch/mipsel/interrupt.rs index f0b3128..d85539e 100644 --- a/kernel/src/arch/mipsel/interrupt.rs +++ b/kernel/src/arch/mipsel/interrupt.rs @@ -129,8 +129,17 @@ fn timer() { fn syscall(tf: &mut TrapFrame) { tf.epc += 4; // Must before syscall, because of fork. - let ret = crate::syscall::syscall(tf.t0, [tf.a0, tf.a1, tf.a2, tf.a3, tf.s0, tf.s1], tf); - tf.v0 = ret as usize; + let arguments = [tf.a0, tf.a1, tf.a2, tf.a3, tf.t0, tf.t1]; + trace!("MIPS syscall {} invoked with {:?}", tf.v0, arguments); + + let ret = crate::syscall::syscall(tf.v0, arguments, tf); + let ret = tf.v0 as isize; + // comply with mips n32 abi, always return a positive value + // https://git.musl-libc.org/cgit/musl/tree/arch/mipsn32/syscall_arch.h + if (ret < 0) { + tf.v0 = (-ret) as usize; + tf.a3 = 1; + } } fn page_fault(tf: &mut TrapFrame) { diff --git a/user b/user index a460c5b..23cfbb6 160000 --- a/user +++ b/user @@ -1 +1 @@ -Subproject commit a460c5b32744292ed50922a159fa22c830aa61b9 +Subproject commit 23cfbb6565377ee88ad0cec3c1fcd3a090ee88c6 From 88bda7c4a04823f3f7804fb380f41c221a62cd35 Mon Sep 17 00:00:00 2001 From: Harry Chen Date: Sun, 7 Apr 2019 17:08:03 +0800 Subject: [PATCH 62/85] Use Linux syscall number for mips N32 ABI, update user app Signed-off-by: Harry Chen --- kernel/Cargo.lock | 69 ++++ kernel/Cargo.toml | 1 + kernel/src/arch/mipsel/syscall.rs | 627 +++++++++++++++++------------- kernel/src/syscall/mod.rs | 2 +- 4 files changed, 418 insertions(+), 281 deletions(-) diff --git a/kernel/Cargo.lock b/kernel/Cargo.lock index d1bd1be..18c5a5e 100644 --- a/kernel/Cargo.lock +++ b/kernel/Cargo.lock @@ -251,6 +251,26 @@ name = "os_bootinfo" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "paste" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "paste-impl 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro-hack 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "paste-impl" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro-hack 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.30 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "pc-keyboard" version = "0.5.0" @@ -264,6 +284,24 @@ dependencies = [ "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "proc-macro-hack" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.30 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "proc-macro2" +version = "0.4.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "pulldown-cmark" version = "0.0.3" @@ -272,6 +310,14 @@ dependencies = [ "getopts 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "quote" +version = "0.6.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "rand" version = "0.4.6" @@ -328,6 +374,7 @@ dependencies = [ "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "mips 0.1.0 (git+https://github.com/Harry-Chen/rust-mips)", "once 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "paste 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "pc-keyboard 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", "pci 0.0.1 (git+https://github.com/rcore-os/pci-rs)", "raw-cpuid 6.1.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -468,6 +515,16 @@ name = "static_assertions" version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "syn" +version = "0.15.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "tempdir" version = "0.3.7" @@ -501,6 +558,11 @@ name = "unicode-width" version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "unicode-xid" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "usize_conversions" version = "0.2.0" @@ -630,9 +692,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum nodrop 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "2f9667ddcc6cc8a43afc9b7917599d7216aa09c463919ea32c59ed6cac8bc945" "checksum once 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "931fb7a4cf34610cf6cbe58d52a8ca5ef4c726d4e2e178abd0dc13a6551c6d73" "checksum os_bootinfo 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "66481dbeb5e773e7bd85b63cd6042c30786f834338288c5ec4f3742673db360a" +"checksum paste 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "1f4a4a1c555c6505821f9d58b8779d0f630a6b7e4e1be24ba718610acf01fa79" +"checksum paste-impl 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "26e796e623b8b257215f27e6c80a5478856cae305f5b59810ff9acdaa34570e6" "checksum pc-keyboard 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c48392db76c4e9a69e0b3be356c5f97ebb7b14413c5e4fd0af4755dbf86e2fce" "checksum pci 0.0.1 (git+https://github.com/rcore-os/pci-rs)" = "" +"checksum proc-macro-hack 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)" = "3e90aa19cd73dedc2d0e1e8407473f073d735fef0ab521438de6da8ee449ab66" +"checksum proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)" = "4d317f9caece796be1980837fd5cb3dfec5613ebdb04ad0956deea83ce168915" "checksum pulldown-cmark 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8361e81576d2e02643b04950e487ec172b687180da65c731c03cf336784e6c07" +"checksum quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)" = "cdd8e04bd9c52e0342b406469d494fcb033be4bdbe5c606016defbb1681411e1" "checksum rand 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "552840b97013b1a26992c11eac34bdd778e464601a4c2054b5f0bff7c6761293" "checksum rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b" "checksum rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d0e7a549d590831370895ab7ba4ea0c1b6b011d106b5ff2da6eee112615e6dc0" @@ -651,11 +718,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum spin 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)" = "ceac490aa12c567115b40b7b7fceca03a6c9d53d5defea066123debc83c5dc1f" "checksum spin 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "44363f6f51401c34e7be73db0db371c04705d35efbe9f7d6082e03a921a32c55" "checksum static_assertions 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "389ce475f424f267dbed6479cbd8f126c5e1afb053b0acdaa019c74305fc65d1" +"checksum syn 0.15.30 (registry+https://github.com/rust-lang/crates.io-index)" = "66c8865bf5a7cbb662d8b011950060b3c8743dca141b054bf7195b20d314d8e2" "checksum tempdir 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "15f2b5fb00ccdf689e0149d1b1b3c03fead81c2b37735d812fa8bddbbf41b6d8" "checksum tock-registers 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3a385d94f3f62e60445a0adb9ff8d9621faa272234530d4c0f848ec98f88e316" "checksum typenum 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "612d636f949607bdf9b123b4a6f6d966dedf3ff669f7f045890d3a4a73948169" "checksum uart_16550 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "269f953d8de3226f7c065c589c7b4a3e83d10a419c7c3b5e2e0f197e6acc966e" "checksum unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "882386231c45df4700b275c7ff55b6f3698780a650026380e72dabe76fa46526" +"checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" "checksum usize_conversions 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f70329e2cbe45d6c97a5112daad40c34cd9a4e18edb5a2a18fefeb584d8d25e5" "checksum ux 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "88dfeb711b61ce620c0cb6fd9f8e3e678622f0c971da2a63c4b3e25e88ed012f" "checksum volatile 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "6af0edf5b4faacc31fc51159244d78d65ec580f021afcef7bd53c04aeabc7f29" diff --git a/kernel/Cargo.toml b/kernel/Cargo.toml index 74ab119..a5c490d 100644 --- a/kernel/Cargo.toml +++ b/kernel/Cargo.toml @@ -79,6 +79,7 @@ bcm2837 = { git = "https://github.com/rcore-os/bcm2837", optional = true } [target.'cfg(target_arch = "mips")'.dependencies] mips = { git = "https://github.com/Harry-Chen/rust-mips" } +paste = "0.1" [package.metadata.bootimage] default-target = "targets/x86_64.json" diff --git a/kernel/src/arch/mipsel/syscall.rs b/kernel/src/arch/mipsel/syscall.rs index b1db116..5a32fb4 100644 --- a/kernel/src/arch/mipsel/syscall.rs +++ b/kernel/src/arch/mipsel/syscall.rs @@ -1,284 +1,351 @@ -//! RISCV32 syscall ids -//! Reference: https://github.com/riscv/riscv-musl/blob/staging/arch/riscv32/bits/syscall.h.in +//! MIPS N32 ABI syscall ids +//! Reference: https://git.linux-mips.org/cgit/ralf/linux.git/tree/arch/mips/include/uapi/asm/unistd.h -pub const SYS_IO_SETUP: usize = 0; -pub const SYS_IO_DESTROY: usize = 1; -pub const SYS_IO_SUBMIT: usize = 2; -pub const SYS_IO_CANCEL: usize = 3; -pub const SYS_IO_GETEVENTS: usize = 4; -pub const SYS_SETXATTR: usize = 5; -pub const SYS_LSETXATTR: usize = 6; -pub const SYS_FSETXATTR: usize = 7; -pub const SYS_GETXATTR: usize = 8; -pub const SYS_LGETXATTR: usize = 9; -pub const SYS_FGETXATTR: usize = 10; -pub const SYS_LISTXATTR: usize = 11; -pub const SYS_LLISTXATTR: usize = 12; -pub const SYS_FLISTXATTR: usize = 13; -pub const SYS_REMOVEXATTR: usize = 14; -pub const SYS_LREMOVEXATTR: usize = 15; -pub const SYS_FREMOVEXATTR: usize = 16; -pub const SYS_GETCWD: usize = 17; -pub const SYS_LOOKUP_DCOOKIE: usize = 18; -pub const SYS_EVENTFD2: usize = 19; -pub const SYS_EPOLL_CREATE1: usize = 20; -pub const SYS_EPOLL_CTL: usize = 21; -pub const SYS_EPOLL_PWAIT: usize = 22; -pub const SYS_DUP: usize = 23; -pub const SYS_DUP3: usize = 24; -pub const SYS_FCNTL: usize = 25; -pub const SYS_INOTIFY_INIT1: usize = 26; -pub const SYS_INOTIFY_ADD_WATCH: usize = 27; -pub const SYS_INOTIFY_RM_WATCH: usize = 28; -pub const SYS_IOCTL: usize = 29; -pub const SYS_IOPRIO_SET: usize = 30; -pub const SYS_IOPRIO_GET: usize = 31; -pub const SYS_FLOCK: usize = 32; -pub const SYS_MKNODAT: usize = 33; -pub const SYS_MKDIRAT: usize = 34; -pub const SYS_UNLINKAT: usize = 35; -pub const SYS_SYMLINKAT: usize = 36; -pub const SYS_LINKAT: usize = 37; -pub const SYS_RENAMEAT: usize = 38; // FIXME -pub const SYS_UMOUNT2: usize = 39; -pub const SYS_MOUNT: usize = 40; -pub const SYS_PIVOT_ROOT: usize = 41; -pub const SYS_NFSSERVCTL: usize = 42; -pub const SYS_STATFS: usize = 43; -pub const SYS_FSTATFS: usize = 44; -pub const SYS_TRUNCATE: usize = 45; -pub const SYS_FTRUNCATE: usize = 46; -pub const SYS_FALLOCATE: usize = 47; -pub const SYS_FACCESSAT: usize = 48; -pub const SYS_CHDIR: usize = 49; -pub const SYS_FCHDIR: usize = 50; -pub const SYS_CHROOT: usize = 51; -pub const SYS_FCHMOD: usize = 52; -pub const SYS_FCHMODAT: usize = 53; -pub const SYS_FCHOWNAT: usize = 54; -pub const SYS_FCHOWN: usize = 55; -pub const SYS_OPENAT: usize = 56; -pub const SYS_CLOSE: usize = 57; -pub const SYS_VHANGUP: usize = 58; -pub const SYS_PIPE2: usize = 59; -pub const SYS_QUOTACTL: usize = 60; -pub const SYS_GETDENTS64: usize = 61; -pub const SYS_LSEEK: usize = 62; -pub const SYS_READ: usize = 63; -pub const SYS_WRITE: usize = 64; -pub const SYS_READV: usize = 65; -pub const SYS_WRITEV: usize = 66; -pub const SYS_PREAD64: usize = 67; -pub const SYS_PWRITE64: usize = 68; -pub const SYS_PREADV: usize = 69; -pub const SYS_PWRITEV: usize = 70; -pub const SYS_SENDFILE: usize = 71; -pub const SYS_PSELECT6: usize = 72; -pub const SYS_PPOLL: usize = 73; -pub const SYS_SIGNALFD4: usize = 74; -pub const SYS_VMSPLICE: usize = 75; -pub const SYS_SPLICE: usize = 76; -pub const SYS_TEE: usize = 77; -pub const SYS_READLINKAT: usize = 78; -pub const SYS_NEWFSTATAT: usize = 79; -pub const SYS_FSTAT: usize = 80; -pub const SYS_SYNC: usize = 81; -pub const SYS_FSYNC: usize = 82; -pub const SYS_FDATASYNC: usize = 83; -pub const SYS_SYNC_FILE_RANGE: usize = 84; -pub const SYS_TIMERFD_CREATE: usize = 85; -pub const SYS_TIMERFD_SETTIME: usize = 86; -pub const SYS_TIMERFD_GETTIME: usize = 87; -pub const SYS_UTIMENSAT: usize = 88; -pub const SYS_ACCT: usize = 89; -pub const SYS_CAPGET: usize = 90; -pub const SYS_CAPSET: usize = 91; -pub const SYS_PERSONALITY: usize = 92; -pub const SYS_EXIT: usize = 93; -pub const SYS_EXIT_GROUP: usize = 94; -pub const SYS_WAITID: usize = 95; -pub const SYS_SET_TID_ADDRESS: usize = 96; -pub const SYS_UNSHARE: usize = 97; -pub const SYS_FUTEX: usize = 98; -pub const SYS_SET_ROBUST_LIST: usize = 99; -pub const SYS_GET_ROBUST_LIST: usize = 100; -pub const SYS_NANOSLEEP: usize = 101; -pub const SYS_GETITIMER: usize = 102; -pub const SYS_SETITIMER: usize = 103; -pub const SYS_KEXEC_LOAD: usize = 104; -pub const SYS_INIT_MODULE: usize = 105; -pub const SYS_DELETE_MODULE: usize = 106; -pub const SYS_TIMER_CREATE: usize = 107; -pub const SYS_TIMER_GETTIME: usize = 108; -pub const SYS_TIMER_GETOVERRUN: usize = 109; -pub const SYS_TIMER_SETTIME: usize = 110; -pub const SYS_TIMER_DELETE: usize = 111; -pub const SYS_CLOCK_SETTIME: usize = 112; -pub const SYS_CLOCK_GETTIME: usize = 113; -pub const SYS_CLOCK_GETRES: usize = 114; -pub const SYS_CLOCK_NANOSLEEP: usize = 115; -pub const SYS_SYSLOG: usize = 116; -pub const SYS_PTRACE: usize = 117; -pub const SYS_SCHED_SETPARAM: usize = 118; -pub const SYS_SCHED_SETSCHEDULER: usize = 119; -pub const SYS_SCHED_GETSCHEDULER: usize = 120; -pub const SYS_SCHED_GETPARAM: usize = 121; -pub const SYS_SCHED_SETAFFINITY: usize = 122; -pub const SYS_SCHED_GETAFFINITY: usize = 123; -pub const SYS_SCHED_YIELD: usize = 124; -pub const SYS_SCHED_GET_PRIORITY_MAX: usize = 125; -pub const SYS_SCHED_GET_PRIORITY_MIN: usize = 126; -pub const SYS_SCHED_RR_GET_INTERVAL: usize = 127; -pub const SYS_RESTART_SYSCALL: usize = 128; -pub const SYS_KILL: usize = 129; -pub const SYS_TKILL: usize = 130; -pub const SYS_TGKILL: usize = 131; -pub const SYS_SIGALTSTACK: usize = 132; -pub const SYS_RT_SIGSUSPEND: usize = 133; -pub const SYS_RT_SIGACTION: usize = 134; -pub const SYS_RT_SIGPROCMASK: usize = 135; -pub const SYS_RT_SIGPENDING: usize = 136; -pub const SYS_RT_SIGTIMEDWAIT: usize = 137; -pub const SYS_RT_SIGQUEUEINFO: usize = 138; -pub const SYS_RT_SIGRETURN: usize = 139; -pub const SYS_SETPRIORITY: usize = 140; -pub const SYS_GETPRIORITY: usize = 141; -pub const SYS_REBOOT: usize = 142; -pub const SYS_SETREGID: usize = 143; -pub const SYS_SETGID: usize = 144; -pub const SYS_SETREUID: usize = 145; -pub const SYS_SETUID: usize = 146; -pub const SYS_SETRESUID: usize = 147; -pub const SYS_GETRESUID: usize = 148; -pub const SYS_SETRESGID: usize = 149; -pub const SYS_GETRESGID: usize = 150; -pub const SYS_SETFSUID: usize = 151; -pub const SYS_SETFSGID: usize = 152; -pub const SYS_TIMES: usize = 153; -pub const SYS_SETPGID: usize = 154; -pub const SYS_GETPGID: usize = 155; -pub const SYS_GETSID: usize = 156; -pub const SYS_SETSID: usize = 157; -pub const SYS_GETGROUPS: usize = 158; -pub const SYS_SETGROUPS: usize = 159; -pub const SYS_UNAME: usize = 160; -pub const SYS_SETHOSTNAME: usize = 161; -pub const SYS_SETDOMAINNAME: usize = 162; -pub const SYS_GETRLIMIT: usize = 163; -pub const SYS_SETRLIMIT: usize = 164; -pub const SYS_GETRUSAGE: usize = 165; -pub const SYS_UMASK: usize = 166; -pub const SYS_PRCTL: usize = 167; -pub const SYS_GETCPU: usize = 168; -pub const SYS_GETTIMEOFDAY: usize = 169; -pub const SYS_SETTIMEOFDAY: usize = 170; -pub const SYS_ADJTIMEX: usize = 171; -pub const SYS_GETPID: usize = 172; -pub const SYS_GETPPID: usize = 173; -pub const SYS_GETUID: usize = 174; -pub const SYS_GETEUID: usize = 175; -pub const SYS_GETGID: usize = 176; -pub const SYS_GETEGID: usize = 177; -pub const SYS_GETTID: usize = 178; -pub const SYS_SYSINFO: usize = 179; -pub const SYS_MQ_OPEN: usize = 180; -pub const SYS_MQ_UNLINK: usize = 181; -pub const SYS_MQ_TIMEDSEND: usize = 182; -pub const SYS_MQ_TIMEDRECEIVE: usize = 183; -pub const SYS_MQ_NOTIFY: usize = 184; -pub const SYS_MQ_GETSETATTR: usize = 185; -pub const SYS_MSGGET: usize = 186; -pub const SYS_MSGCTL: usize = 187; -pub const SYS_MSGRCV: usize = 188; -pub const SYS_MSGSND: usize = 189; -pub const SYS_SEMGET: usize = 190; -pub const SYS_SEMCTL: usize = 191; -pub const SYS_SEMTIMEDOP: usize = 192; -pub const SYS_SEMOP: usize = 193; -pub const SYS_SHMGET: usize = 194; -pub const SYS_SHMCTL: usize = 195; -pub const SYS_SHMAT: usize = 196; -pub const SYS_SHMDT: usize = 197; -pub const SYS_SOCKET: usize = 198; -pub const SYS_SOCKETPAIR: usize = 199; -pub const SYS_BIND: usize = 200; -pub const SYS_LISTEN: usize = 201; -pub const SYS_ACCEPT: usize = 202; -pub const SYS_CONNECT: usize = 203; -pub const SYS_GETSOCKNAME: usize = 204; -pub const SYS_GETPEERNAME: usize = 205; -pub const SYS_SENDTO: usize = 206; -pub const SYS_RECVFROM: usize = 207; -pub const SYS_SETSOCKOPT: usize = 208; -pub const SYS_GETSOCKOPT: usize = 209; -pub const SYS_SHUTDOWN: usize = 210; -pub const SYS_SENDMSG: usize = 211; -pub const SYS_RECVMSG: usize = 212; -pub const SYS_READAHEAD: usize = 213; -pub const SYS_BRK: usize = 214; -pub const SYS_MUNMAP: usize = 215; -pub const SYS_MREMAP: usize = 216; -pub const SYS_ADD_KEY: usize = 217; -pub const SYS_REQUEST_KEY: usize = 218; -pub const SYS_KEYCTL: usize = 219; -pub const SYS_CLONE: usize = 220; -pub const SYS_EXECVE: usize = 221; -pub const SYS_MMAP: usize = 222; -pub const SYS_FADVISE64: usize = 223; -pub const SYS_SWAPON: usize = 224; -pub const SYS_SWAPOFF: usize = 225; -pub const SYS_MPROTECT: usize = 226; -pub const SYS_MSYNC: usize = 227; -pub const SYS_MLOCK: usize = 228; -pub const SYS_MUNLOCK: usize = 229; -pub const SYS_MLOCKALL: usize = 230; -pub const SYS_MUNLOCKALL: usize = 231; -pub const SYS_MINCORE: usize = 232; -pub const SYS_MADVISE: usize = 233; -pub const SYS_REMAP_FILE_PAGES: usize = 234; -pub const SYS_MBIND: usize = 235; -pub const SYS_GET_MEMPOLICY: usize = 236; -pub const SYS_SET_MEMPOLICY: usize = 237; -pub const SYS_MIGRATE_PAGES: usize = 238; -pub const SYS_MOVE_PAGES: usize = 239; -pub const SYS_RT_TGSIGQUEUEINFO: usize = 240; -pub const SYS_PERF_EVENT_OPEN: usize = 241; -pub const SYS_ACCEPT4: usize = 242; -pub const SYS_RECVMMSG: usize = 243; -pub const SYS_ARCH_SPECIFIC_SYSCALL: usize = 244; -pub const SYS_WAIT4: usize = 260; -pub const SYS_PRLIMIT64: usize = 261; -pub const SYS_FANOTIFY_INIT: usize = 262; -pub const SYS_FANOTIFY_MARK: usize = 263; -pub const SYS_NAME_TO_HANDLE_AT: usize = 264; -pub const SYS_OPEN_BY_HANDLE_AT: usize = 265; -pub const SYS_CLOCK_ADJTIME: usize = 266; -pub const SYS_SYNCFS: usize = 267; -pub const SYS_SETNS: usize = 268; -pub const SYS_SENDMMSG: usize = 269; -pub const SYS_PROCESS_VM_READV: usize = 270; -pub const SYS_PROCESS_VM_WRITEV: usize = 271; -pub const SYS_KCMP: usize = 272; -pub const SYS_FINIT_MODULE: usize = 273; -pub const SYS_SCHED_SETATTR: usize = 274; -pub const SYS_SCHED_GETATTR: usize = 275; -pub const SYS_RENAMEAT2: usize = 276; -pub const SYS_SECCOMP: usize = 277; -pub const SYS_GETRANDOM: usize = 278; -pub const SYS_MEMFD_CREATE: usize = 279; -pub const SYS_BPF: usize = 280; -pub const SYS_EXECVEAT: usize = 281; -pub const SYS_USERFAULTFD: usize = 282; -pub const SYS_MEMBARRIER: usize = 283; -pub const SYS_MLOCK2: usize = 284; -pub const SYS_COPY_FILE_RANGE: usize = 285; -pub const SYS_PREADV2: usize = 286; -pub const SYS_PWRITEV2: usize = 287; -pub const SYS_PKEY_MPROTECT: usize = 288; -pub const SYS_PKEY_ALLOC: usize = 289; -pub const SYS_PKEY_FREE: usize = 290; -pub const SYS_SYSRISCV: usize = SYS_ARCH_SPECIFIC_SYSCALL; -pub const SYS_RISCV_FLUSH_ICACHE: usize = SYS_SYSRISCV + 15; +extern crate paste; + +pub const MIPS_SYSCALL_OFFSET: usize = 6000; + +macro_rules! define_syscall { + ($name: ident, $id: expr) => { + paste::item! { + pub const [] : usize = MIPS_SYSCALL_OFFSET + $id; + } + }; +} + +define_syscall!(READ, 0); +define_syscall!(WRITE, 1); +define_syscall!(OPEN, 2); +define_syscall!(CLOSE, 3); +define_syscall!(STAT, 4); +define_syscall!(FSTAT, 5); +define_syscall!(LSTAT, 6); +define_syscall!(POLL, 7); +define_syscall!(LSEEK, 8); +define_syscall!(MMAP, 9); +define_syscall!(MPROTECT, 10); +define_syscall!(MUNMAP, 11); +define_syscall!(BRK, 12); +define_syscall!(RT_SIGACTION, 13); +define_syscall!(RT_SIGPROCMASK, 14); +define_syscall!(IOCTL, 15); +define_syscall!(PREAD64, 16); +define_syscall!(PWRITE64, 17); +define_syscall!(READV, 18); +define_syscall!(WRITEV, 19); +define_syscall!(ACCESS, 20); +define_syscall!(PIPE, 21); +define_syscall!(_NEWSELECT, 22); +define_syscall!(SCHED_YIELD, 23); +define_syscall!(MREMAP, 24); +define_syscall!(MSYNC, 25); +define_syscall!(MINCORE, 26); +define_syscall!(MADVISE, 27); +define_syscall!(SHMGET, 28); +define_syscall!(SHMAT, 29); +define_syscall!(SHMCTL, 30); +define_syscall!(DUP, 31); +define_syscall!(DUP2, 32); +define_syscall!(PAUSE, 33); +define_syscall!(NANOSLEEP, 34); +define_syscall!(GETITIMER, 35); +define_syscall!(SETITIMER, 36); +define_syscall!(ALARM, 37); +define_syscall!(GETPID, 38); +define_syscall!(SENDFILE, 39); +define_syscall!(SOCKET, 40); +define_syscall!(CONNECT, 41); +define_syscall!(ACCEPT, 42); +define_syscall!(SENDTO, 43); +define_syscall!(RECVFROM, 44); +define_syscall!(SENDMSG, 45); +define_syscall!(RECVMSG, 46); +define_syscall!(SHUTDOWN, 47); +define_syscall!(BIND, 48); +define_syscall!(LISTEN, 49); +define_syscall!(GETSOCKNAME, 50); +define_syscall!(GETPEERNAME, 51); +define_syscall!(SOCKETPAIR, 52); +define_syscall!(SETSOCKOPT, 53); +define_syscall!(GETSOCKOPT, 54); +define_syscall!(CLONE, 55); +define_syscall!(FORK, 56); +define_syscall!(EXECVE, 57); +define_syscall!(EXIT, 58); +define_syscall!(WAIT4, 59); +define_syscall!(KILL, 60); +define_syscall!(UNAME, 61); +define_syscall!(SEMGET, 62); +define_syscall!(SEMOP, 63); +define_syscall!(SEMCTL, 64); +define_syscall!(SHMDT, 65); +define_syscall!(MSGGET, 66); +define_syscall!(MSGSND, 67); +define_syscall!(MSGRCV, 68); +define_syscall!(MSGCTL, 69); +define_syscall!(FCNTL, 70); +define_syscall!(FLOCK, 71); +define_syscall!(FSYNC, 72); +define_syscall!(FDATASYNC, 73); +define_syscall!(TRUNCATE, 74); +define_syscall!(FTRUNCATE, 75); +define_syscall!(GETDENTS, 76); +define_syscall!(GETCWD, 77); +define_syscall!(CHDIR, 78); +define_syscall!(FCHDIR, 79); +define_syscall!(RENAME, 80); +define_syscall!(MKDIR, 81); +define_syscall!(RMDIR, 82); +define_syscall!(CREAT, 83); +define_syscall!(LINK, 84); +define_syscall!(UNLINK, 85); +define_syscall!(SYMLINK, 86); +define_syscall!(READLINK, 87); +define_syscall!(CHMOD, 88); +define_syscall!(FCHMOD, 89); +define_syscall!(CHOWN, 90); +define_syscall!(FCHOWN, 91); +define_syscall!(LCHOWN, 92); +define_syscall!(UMASK, 93); +define_syscall!(GETTIMEOFDAY, 94); +define_syscall!(GETRLIMIT, 95); +define_syscall!(GETRUSAGE, 96); +define_syscall!(SYSINFO, 97); +define_syscall!(TIMES, 98); +define_syscall!(PTRACE, 99); +define_syscall!(GETUID, 100); +define_syscall!(SYSLOG, 101); +define_syscall!(GETGID, 102); +define_syscall!(SETUID, 103); +define_syscall!(SETGID, 104); +define_syscall!(GETEUID, 105); +define_syscall!(GETEGID, 106); +define_syscall!(SETPGID, 107); +define_syscall!(GETPPID, 108); +define_syscall!(GETPGRP, 109); +define_syscall!(SETSID, 110); +define_syscall!(SETREUID, 111); +define_syscall!(SETREGID, 112); +define_syscall!(GETGROUPS, 113); +define_syscall!(SETGROUPS, 114); +define_syscall!(SETRESUID, 115); +define_syscall!(GETRESUID, 116); +define_syscall!(SETRESGID, 117); +define_syscall!(GETRESGID, 118); +define_syscall!(GETPGID, 119); +define_syscall!(SETFSUID, 120); +define_syscall!(SETFSGID, 121); +define_syscall!(GETSID, 122); +define_syscall!(CAPGET, 123); +define_syscall!(CAPSET, 124); +define_syscall!(RT_SIGPENDING, 125); +define_syscall!(RT_SIGTIMEDWAIT, 126); +define_syscall!(RT_SIGQUEUEINFO, 127); +define_syscall!(RT_SIGSUSPEND, 128); +define_syscall!(SIGALTSTACK, 129); +define_syscall!(UTIME, 130); +define_syscall!(MKNOD, 131); +define_syscall!(PERSONALITY, 132); +define_syscall!(USTAT, 133); +define_syscall!(STATFS, 134); +define_syscall!(FSTATFS, 135); +define_syscall!(SYSFS, 136); +define_syscall!(GETPRIORITY, 137); +define_syscall!(SETPRIORITY, 138); +define_syscall!(SCHED_SETPARAM, 139); +define_syscall!(SCHED_GETPARAM, 140); +define_syscall!(SCHED_SETSCHEDULER, 141); +define_syscall!(SCHED_GETSCHEDULER, 142); +define_syscall!(SCHED_GET_PRIORITY_MAX, 143); +define_syscall!(SCHED_GET_PRIORITY_MIN, 144); +define_syscall!(SCHED_RR_GET_INTERVAL, 145); +define_syscall!(MLOCK, 146); +define_syscall!(MUNLOCK, 147); +define_syscall!(MLOCKALL, 148); +define_syscall!(MUNLOCKALL, 149); +define_syscall!(VHANGUP, 150); +define_syscall!(PIVOT_ROOT, 151); +define_syscall!(_SYSCTL, 152); +define_syscall!(PRCTL, 153); +define_syscall!(ADJTIMEX, 154); +define_syscall!(SETRLIMIT, 155); +define_syscall!(CHROOT, 156); +define_syscall!(SYNC, 157); +define_syscall!(ACCT, 158); +define_syscall!(SETTIMEOFDAY, 159); +define_syscall!(MOUNT, 160); +define_syscall!(UMOUNT2, 161); +define_syscall!(SWAPON, 162); +define_syscall!(SWAPOFF, 163); +define_syscall!(REBOOT, 164); +define_syscall!(SETHOSTNAME, 165); +define_syscall!(SETDOMAINNAME, 166); +define_syscall!(CREATE_MODULE, 167); +define_syscall!(INIT_MODULE, 168); +define_syscall!(DELETE_MODULE, 169); +define_syscall!(GET_KERNEL_SYMS, 170); +define_syscall!(QUERY_MODULE, 171); +define_syscall!(QUOTACTL, 172); +define_syscall!(NFSSERVCTL, 173); +define_syscall!(GETPMSG, 174); +define_syscall!(PUTPMSG, 175); +define_syscall!(AFS_SYSCALL, 176); +define_syscall!(RESERVED177, 177); +define_syscall!(GETTID, 178); +define_syscall!(READAHEAD, 179); +define_syscall!(SETXATTR, 180); +define_syscall!(LSETXATTR, 181); +define_syscall!(FSETXATTR, 182); +define_syscall!(GETXATTR, 183); +define_syscall!(LGETXATTR, 184); +define_syscall!(FGETXATTR, 185); +define_syscall!(LISTXATTR, 186); +define_syscall!(LLISTXATTR, 187); +define_syscall!(FLISTXATTR, 188); +define_syscall!(REMOVEXATTR, 189); +define_syscall!(LREMOVEXATTR, 190); +define_syscall!(FREMOVEXATTR, 191); +define_syscall!(TKILL, 192); +define_syscall!(RESERVED193, 193); +define_syscall!(FUTEX, 194); +define_syscall!(SCHED_SETAFFINITY, 195); +define_syscall!(SCHED_GETAFFINITY, 196); +define_syscall!(CACHEFLUSH, 197); +define_syscall!(CACHECTL, 198); +define_syscall!(SYSMIPS, 199); +define_syscall!(IO_SETUP, 200); +define_syscall!(IO_DESTROY, 201); +define_syscall!(IO_GETEVENTS, 202); +define_syscall!(IO_SUBMIT, 203); +define_syscall!(IO_CANCEL, 204); +define_syscall!(EXIT_GROUP, 205); +define_syscall!(LOOKUP_DCOOKIE, 206); +define_syscall!(EPOLL_CREATE, 207); +define_syscall!(EPOLL_CTL, 208); +define_syscall!(EPOLL_WAIT, 209); +define_syscall!(REMAP_FILE_PAGES, 210); +define_syscall!(RT_SIGRETURN, 211); +define_syscall!(FCNTL64, 212); +define_syscall!(SET_TID_ADDRESS, 213); +define_syscall!(RESTART_SYSCALL, 214); +define_syscall!(SEMTIMEDOP, 215); +define_syscall!(FADVISE64, 216); +define_syscall!(STATFS64, 217); +define_syscall!(FSTATFS64, 218); +define_syscall!(SENDFILE64, 219); +define_syscall!(TIMER_CREATE, 220); +define_syscall!(TIMER_SETTIME, 221); +define_syscall!(TIMER_GETTIME, 222); +define_syscall!(TIMER_GETOVERRUN, 223); +define_syscall!(TIMER_DELETE, 224); +define_syscall!(CLOCK_SETTIME, 225); +define_syscall!(CLOCK_GETTIME, 226); +define_syscall!(CLOCK_GETRES, 227); +define_syscall!(CLOCK_NANOSLEEP, 228); +define_syscall!(TGKILL, 229); +define_syscall!(UTIMES, 230); +define_syscall!(MBIND, 231); +define_syscall!(GET_MEMPOLICY, 232); +define_syscall!(SET_MEMPOLICY, 233); +define_syscall!(MQ_OPEN, 234); +define_syscall!(MQ_UNLINK, 235); +define_syscall!(MQ_TIMEDSEND, 236); +define_syscall!(MQ_TIMEDRECEIVE, 237); +define_syscall!(MQ_NOTIFY, 238); +define_syscall!(MQ_GETSETATTR, 239); +define_syscall!(VSERVER, 240); +define_syscall!(WAITID, 241); +define_syscall!(SYS_SETALTROOT, 242); +define_syscall!(ADD_KEY, 243); +define_syscall!(REQUEST_KEY, 244); +define_syscall!(KEYCTL, 245); +define_syscall!(SET_THREAD_AREA, 246); +define_syscall!(INOTIFY_INIT, 247); +define_syscall!(INOTIFY_ADD_WATCH, 248); +define_syscall!(INOTIFY_RM_WATCH, 249); +define_syscall!(MIGRATE_PAGES, 250); +define_syscall!(OPENAT, 251); +define_syscall!(MKDIRAT, 252); +define_syscall!(MKNODAT, 253); +define_syscall!(FCHOWNAT, 254); +define_syscall!(FUTIMESAT, 255); +define_syscall!(NEWFSTATAT, 256); +define_syscall!(UNLINKAT, 257); +define_syscall!(RENAMEAT, 258); +define_syscall!(LINKAT, 259); +define_syscall!(SYMLINKAT, 260); +define_syscall!(READLINKAT, 261); +define_syscall!(FCHMODAT, 262); +define_syscall!(FACCESSAT, 263); +define_syscall!(PSELECT6, 264); +define_syscall!(PPOLL, 265); +define_syscall!(UNSHARE, 266); +define_syscall!(SPLICE, 267); +define_syscall!(SYNC_FILE_RANGE, 268); +define_syscall!(TEE, 269); +define_syscall!(VMSPLICE, 270); +define_syscall!(MOVE_PAGES, 271); +define_syscall!(SET_ROBUST_LIST, 272); +define_syscall!(GET_ROBUST_LIST, 273); +define_syscall!(KEXEC_LOAD, 274); +define_syscall!(GETCPU, 275); +define_syscall!(EPOLL_PWAIT, 276); +define_syscall!(IOPRIO_SET, 277); +define_syscall!(IOPRIO_GET, 278); +define_syscall!(UTIMENSAT, 279); +define_syscall!(SIGNALFD, 280); +define_syscall!(TIMERFD, 281); +define_syscall!(EVENTFD, 282); +define_syscall!(FALLOCATE, 283); +define_syscall!(TIMERFD_CREATE, 284); +define_syscall!(TIMERFD_GETTIME, 285); +define_syscall!(TIMERFD_SETTIME, 286); +define_syscall!(SIGNALFD4, 287); +define_syscall!(EVENTFD2, 288); +define_syscall!(EPOLL_CREATE1, 289); +define_syscall!(DUP3, 290); +define_syscall!(PIPE2, 291); +define_syscall!(INOTIFY_INIT1, 292); +define_syscall!(PREADV, 293); +define_syscall!(PWRITEV, 294); +define_syscall!(RT_TGSIGQUEUEINFO, 295); +define_syscall!(PERF_EVENT_OPEN, 296); +define_syscall!(ACCEPT4, 297); +define_syscall!(RECVMMSG, 298); +define_syscall!(GETDENTS64, 299); +define_syscall!(FANOTIFY_INIT, 300); +define_syscall!(FANOTIFY_MARK, 301); +define_syscall!(PRLIMIT64, 302); +define_syscall!(NAME_TO_HANDLE_AT, 303); +define_syscall!(OPEN_BY_HANDLE_AT, 304); +define_syscall!(CLOCK_ADJTIME, 305); +define_syscall!(SYNCFS, 306); +define_syscall!(SENDMMSG, 307); +define_syscall!(SETNS, 308); +define_syscall!(PROCESS_VM_READV, 309); +define_syscall!(PROCESS_VM_WRITEV, 310); +define_syscall!(KCMP, 311); +define_syscall!(FINIT_MODULE, 312); +define_syscall!(SCHED_SETATTR, 313); +define_syscall!(SCHED_GETATTR, 314); +define_syscall!(RENAMEAT2, 315); +define_syscall!(SECCOMP, 316); +define_syscall!(GETRANDOM, 317); +define_syscall!(MEMFD_CREATE, 318); +define_syscall!(BPF, 319); +define_syscall!(EXECVEAT, 320); +define_syscall!(USERFAULTFD, 321); +define_syscall!(MEMBARRIER, 322); +define_syscall!(MLOCK2, 323); +define_syscall!(COPY_FILE_RANGE, 324); +define_syscall!(PREADV2, 325); +define_syscall!(PWRITEV2, 326); +define_syscall!(PKEY_MPROTECT, 327); +define_syscall!(PKEY_ALLOC, 328); +define_syscall!(PKEY_FREE, 329); +define_syscall!(STATX, 330); +define_syscall!(RSEQ, 331); +define_syscall!(IO_PGETEVENTS, 332); // custom temporary syscall pub const SYS_MAP_PCI_DEVICE: usize = 999; diff --git a/kernel/src/syscall/mod.rs b/kernel/src/syscall/mod.rs index d8fc481..0787d83 100644 --- a/kernel/src/syscall/mod.rs +++ b/kernel/src/syscall/mod.rs @@ -44,7 +44,7 @@ pub fn syscall(id: usize, args: [usize; 6], tf: &mut TrapFrame) -> isize { debug!("{}:{}:{} syscall id {} begin", cid, pid, tid, id); } - // use syscall numbers in Linux x86_64 + // use platform-specific syscal numbers // See https://filippo.io/linux-syscall-table/ // And https://fedora.juszkiewicz.com.pl/syscalls.html. let ret = match id { From b1fa65b9c9f60a320709e0f3a6d66dc96ade7031 Mon Sep 17 00:00:00 2001 From: Harry Chen Date: Sun, 7 Apr 2019 18:04:28 +0800 Subject: [PATCH 63/85] Use syscall from MIPS o32 ABI, read boot command line in dts from Signed-off-by: Harry Chen --- kernel/Makefile | 4 +- kernel/src/arch/mipsel/board/malta/device.dts | 1 + kernel/src/arch/mipsel/syscall.rs | 707 +++++++++--------- user | 2 +- 4 files changed, 378 insertions(+), 336 deletions(-) diff --git a/kernel/Makefile b/kernel/Makefile index 8d7fc9e..9466a82 100644 --- a/kernel/Makefile +++ b/kernel/Makefile @@ -262,7 +262,9 @@ sym: ### device tree process ### %.dtb: %.dts - $(dtc) -I dts -O dtb -o $@ $< + @echo Generating device tree file $@ + @$(dtc) -I dts -O dtb -o $@ $< + @rm -rf src/arch/${arch}/boot/dtb.gen.s ### bootloader and kernel image ### diff --git a/kernel/src/arch/mipsel/board/malta/device.dts b/kernel/src/arch/mipsel/board/malta/device.dts index ddaaa72..bbe1e66 100644 --- a/kernel/src/arch/mipsel/board/malta/device.dts +++ b/kernel/src/arch/mipsel/board/malta/device.dts @@ -9,6 +9,7 @@ chosen { stdio = &uart2; + bootargs = "rust/sh"; }; aliases { }; diff --git a/kernel/src/arch/mipsel/syscall.rs b/kernel/src/arch/mipsel/syscall.rs index 5a32fb4..7e1144f 100644 --- a/kernel/src/arch/mipsel/syscall.rs +++ b/kernel/src/arch/mipsel/syscall.rs @@ -3,7 +3,7 @@ extern crate paste; -pub const MIPS_SYSCALL_OFFSET: usize = 6000; +pub const MIPS_SYSCALL_OFFSET: usize = 4000; macro_rules! define_syscall { ($name: ident, $id: expr) => { @@ -13,339 +13,378 @@ macro_rules! define_syscall { }; } -define_syscall!(READ, 0); -define_syscall!(WRITE, 1); -define_syscall!(OPEN, 2); -define_syscall!(CLOSE, 3); -define_syscall!(STAT, 4); -define_syscall!(FSTAT, 5); -define_syscall!(LSTAT, 6); -define_syscall!(POLL, 7); -define_syscall!(LSEEK, 8); -define_syscall!(MMAP, 9); -define_syscall!(MPROTECT, 10); -define_syscall!(MUNMAP, 11); -define_syscall!(BRK, 12); -define_syscall!(RT_SIGACTION, 13); -define_syscall!(RT_SIGPROCMASK, 14); -define_syscall!(IOCTL, 15); -define_syscall!(PREAD64, 16); -define_syscall!(PWRITE64, 17); -define_syscall!(READV, 18); -define_syscall!(WRITEV, 19); -define_syscall!(ACCESS, 20); -define_syscall!(PIPE, 21); -define_syscall!(_NEWSELECT, 22); -define_syscall!(SCHED_YIELD, 23); -define_syscall!(MREMAP, 24); -define_syscall!(MSYNC, 25); -define_syscall!(MINCORE, 26); -define_syscall!(MADVISE, 27); -define_syscall!(SHMGET, 28); -define_syscall!(SHMAT, 29); -define_syscall!(SHMCTL, 30); -define_syscall!(DUP, 31); -define_syscall!(DUP2, 32); -define_syscall!(PAUSE, 33); -define_syscall!(NANOSLEEP, 34); -define_syscall!(GETITIMER, 35); -define_syscall!(SETITIMER, 36); -define_syscall!(ALARM, 37); -define_syscall!(GETPID, 38); -define_syscall!(SENDFILE, 39); -define_syscall!(SOCKET, 40); -define_syscall!(CONNECT, 41); -define_syscall!(ACCEPT, 42); -define_syscall!(SENDTO, 43); -define_syscall!(RECVFROM, 44); -define_syscall!(SENDMSG, 45); -define_syscall!(RECVMSG, 46); -define_syscall!(SHUTDOWN, 47); -define_syscall!(BIND, 48); -define_syscall!(LISTEN, 49); -define_syscall!(GETSOCKNAME, 50); -define_syscall!(GETPEERNAME, 51); -define_syscall!(SOCKETPAIR, 52); -define_syscall!(SETSOCKOPT, 53); -define_syscall!(GETSOCKOPT, 54); -define_syscall!(CLONE, 55); -define_syscall!(FORK, 56); -define_syscall!(EXECVE, 57); -define_syscall!(EXIT, 58); -define_syscall!(WAIT4, 59); -define_syscall!(KILL, 60); -define_syscall!(UNAME, 61); -define_syscall!(SEMGET, 62); -define_syscall!(SEMOP, 63); -define_syscall!(SEMCTL, 64); -define_syscall!(SHMDT, 65); -define_syscall!(MSGGET, 66); -define_syscall!(MSGSND, 67); -define_syscall!(MSGRCV, 68); -define_syscall!(MSGCTL, 69); -define_syscall!(FCNTL, 70); -define_syscall!(FLOCK, 71); -define_syscall!(FSYNC, 72); -define_syscall!(FDATASYNC, 73); -define_syscall!(TRUNCATE, 74); -define_syscall!(FTRUNCATE, 75); -define_syscall!(GETDENTS, 76); -define_syscall!(GETCWD, 77); -define_syscall!(CHDIR, 78); -define_syscall!(FCHDIR, 79); -define_syscall!(RENAME, 80); -define_syscall!(MKDIR, 81); -define_syscall!(RMDIR, 82); -define_syscall!(CREAT, 83); -define_syscall!(LINK, 84); -define_syscall!(UNLINK, 85); -define_syscall!(SYMLINK, 86); -define_syscall!(READLINK, 87); -define_syscall!(CHMOD, 88); -define_syscall!(FCHMOD, 89); -define_syscall!(CHOWN, 90); -define_syscall!(FCHOWN, 91); -define_syscall!(LCHOWN, 92); -define_syscall!(UMASK, 93); -define_syscall!(GETTIMEOFDAY, 94); -define_syscall!(GETRLIMIT, 95); -define_syscall!(GETRUSAGE, 96); -define_syscall!(SYSINFO, 97); -define_syscall!(TIMES, 98); -define_syscall!(PTRACE, 99); -define_syscall!(GETUID, 100); -define_syscall!(SYSLOG, 101); -define_syscall!(GETGID, 102); -define_syscall!(SETUID, 103); -define_syscall!(SETGID, 104); -define_syscall!(GETEUID, 105); -define_syscall!(GETEGID, 106); -define_syscall!(SETPGID, 107); -define_syscall!(GETPPID, 108); -define_syscall!(GETPGRP, 109); -define_syscall!(SETSID, 110); -define_syscall!(SETREUID, 111); -define_syscall!(SETREGID, 112); -define_syscall!(GETGROUPS, 113); -define_syscall!(SETGROUPS, 114); -define_syscall!(SETRESUID, 115); -define_syscall!(GETRESUID, 116); -define_syscall!(SETRESGID, 117); -define_syscall!(GETRESGID, 118); -define_syscall!(GETPGID, 119); -define_syscall!(SETFSUID, 120); -define_syscall!(SETFSGID, 121); -define_syscall!(GETSID, 122); -define_syscall!(CAPGET, 123); -define_syscall!(CAPSET, 124); -define_syscall!(RT_SIGPENDING, 125); -define_syscall!(RT_SIGTIMEDWAIT, 126); -define_syscall!(RT_SIGQUEUEINFO, 127); -define_syscall!(RT_SIGSUSPEND, 128); -define_syscall!(SIGALTSTACK, 129); -define_syscall!(UTIME, 130); -define_syscall!(MKNOD, 131); -define_syscall!(PERSONALITY, 132); -define_syscall!(USTAT, 133); -define_syscall!(STATFS, 134); -define_syscall!(FSTATFS, 135); -define_syscall!(SYSFS, 136); -define_syscall!(GETPRIORITY, 137); -define_syscall!(SETPRIORITY, 138); -define_syscall!(SCHED_SETPARAM, 139); -define_syscall!(SCHED_GETPARAM, 140); -define_syscall!(SCHED_SETSCHEDULER, 141); -define_syscall!(SCHED_GETSCHEDULER, 142); -define_syscall!(SCHED_GET_PRIORITY_MAX, 143); -define_syscall!(SCHED_GET_PRIORITY_MIN, 144); -define_syscall!(SCHED_RR_GET_INTERVAL, 145); -define_syscall!(MLOCK, 146); -define_syscall!(MUNLOCK, 147); -define_syscall!(MLOCKALL, 148); -define_syscall!(MUNLOCKALL, 149); -define_syscall!(VHANGUP, 150); -define_syscall!(PIVOT_ROOT, 151); -define_syscall!(_SYSCTL, 152); -define_syscall!(PRCTL, 153); -define_syscall!(ADJTIMEX, 154); -define_syscall!(SETRLIMIT, 155); -define_syscall!(CHROOT, 156); -define_syscall!(SYNC, 157); -define_syscall!(ACCT, 158); -define_syscall!(SETTIMEOFDAY, 159); -define_syscall!(MOUNT, 160); -define_syscall!(UMOUNT2, 161); -define_syscall!(SWAPON, 162); -define_syscall!(SWAPOFF, 163); -define_syscall!(REBOOT, 164); -define_syscall!(SETHOSTNAME, 165); -define_syscall!(SETDOMAINNAME, 166); -define_syscall!(CREATE_MODULE, 167); -define_syscall!(INIT_MODULE, 168); -define_syscall!(DELETE_MODULE, 169); -define_syscall!(GET_KERNEL_SYMS, 170); -define_syscall!(QUERY_MODULE, 171); -define_syscall!(QUOTACTL, 172); -define_syscall!(NFSSERVCTL, 173); -define_syscall!(GETPMSG, 174); -define_syscall!(PUTPMSG, 175); -define_syscall!(AFS_SYSCALL, 176); -define_syscall!(RESERVED177, 177); -define_syscall!(GETTID, 178); -define_syscall!(READAHEAD, 179); -define_syscall!(SETXATTR, 180); -define_syscall!(LSETXATTR, 181); -define_syscall!(FSETXATTR, 182); -define_syscall!(GETXATTR, 183); -define_syscall!(LGETXATTR, 184); -define_syscall!(FGETXATTR, 185); -define_syscall!(LISTXATTR, 186); -define_syscall!(LLISTXATTR, 187); -define_syscall!(FLISTXATTR, 188); -define_syscall!(REMOVEXATTR, 189); -define_syscall!(LREMOVEXATTR, 190); -define_syscall!(FREMOVEXATTR, 191); -define_syscall!(TKILL, 192); -define_syscall!(RESERVED193, 193); -define_syscall!(FUTEX, 194); -define_syscall!(SCHED_SETAFFINITY, 195); -define_syscall!(SCHED_GETAFFINITY, 196); -define_syscall!(CACHEFLUSH, 197); -define_syscall!(CACHECTL, 198); -define_syscall!(SYSMIPS, 199); -define_syscall!(IO_SETUP, 200); -define_syscall!(IO_DESTROY, 201); -define_syscall!(IO_GETEVENTS, 202); -define_syscall!(IO_SUBMIT, 203); -define_syscall!(IO_CANCEL, 204); -define_syscall!(EXIT_GROUP, 205); -define_syscall!(LOOKUP_DCOOKIE, 206); -define_syscall!(EPOLL_CREATE, 207); -define_syscall!(EPOLL_CTL, 208); -define_syscall!(EPOLL_WAIT, 209); -define_syscall!(REMAP_FILE_PAGES, 210); -define_syscall!(RT_SIGRETURN, 211); -define_syscall!(FCNTL64, 212); -define_syscall!(SET_TID_ADDRESS, 213); -define_syscall!(RESTART_SYSCALL, 214); -define_syscall!(SEMTIMEDOP, 215); -define_syscall!(FADVISE64, 216); -define_syscall!(STATFS64, 217); -define_syscall!(FSTATFS64, 218); -define_syscall!(SENDFILE64, 219); -define_syscall!(TIMER_CREATE, 220); -define_syscall!(TIMER_SETTIME, 221); -define_syscall!(TIMER_GETTIME, 222); -define_syscall!(TIMER_GETOVERRUN, 223); -define_syscall!(TIMER_DELETE, 224); -define_syscall!(CLOCK_SETTIME, 225); -define_syscall!(CLOCK_GETTIME, 226); -define_syscall!(CLOCK_GETRES, 227); -define_syscall!(CLOCK_NANOSLEEP, 228); -define_syscall!(TGKILL, 229); -define_syscall!(UTIMES, 230); -define_syscall!(MBIND, 231); -define_syscall!(GET_MEMPOLICY, 232); -define_syscall!(SET_MEMPOLICY, 233); -define_syscall!(MQ_OPEN, 234); -define_syscall!(MQ_UNLINK, 235); -define_syscall!(MQ_TIMEDSEND, 236); -define_syscall!(MQ_TIMEDRECEIVE, 237); -define_syscall!(MQ_NOTIFY, 238); -define_syscall!(MQ_GETSETATTR, 239); -define_syscall!(VSERVER, 240); -define_syscall!(WAITID, 241); -define_syscall!(SYS_SETALTROOT, 242); -define_syscall!(ADD_KEY, 243); -define_syscall!(REQUEST_KEY, 244); -define_syscall!(KEYCTL, 245); -define_syscall!(SET_THREAD_AREA, 246); -define_syscall!(INOTIFY_INIT, 247); -define_syscall!(INOTIFY_ADD_WATCH, 248); -define_syscall!(INOTIFY_RM_WATCH, 249); -define_syscall!(MIGRATE_PAGES, 250); -define_syscall!(OPENAT, 251); -define_syscall!(MKDIRAT, 252); -define_syscall!(MKNODAT, 253); -define_syscall!(FCHOWNAT, 254); -define_syscall!(FUTIMESAT, 255); -define_syscall!(NEWFSTATAT, 256); -define_syscall!(UNLINKAT, 257); -define_syscall!(RENAMEAT, 258); -define_syscall!(LINKAT, 259); -define_syscall!(SYMLINKAT, 260); -define_syscall!(READLINKAT, 261); -define_syscall!(FCHMODAT, 262); -define_syscall!(FACCESSAT, 263); -define_syscall!(PSELECT6, 264); -define_syscall!(PPOLL, 265); -define_syscall!(UNSHARE, 266); -define_syscall!(SPLICE, 267); -define_syscall!(SYNC_FILE_RANGE, 268); -define_syscall!(TEE, 269); -define_syscall!(VMSPLICE, 270); -define_syscall!(MOVE_PAGES, 271); -define_syscall!(SET_ROBUST_LIST, 272); -define_syscall!(GET_ROBUST_LIST, 273); -define_syscall!(KEXEC_LOAD, 274); -define_syscall!(GETCPU, 275); -define_syscall!(EPOLL_PWAIT, 276); -define_syscall!(IOPRIO_SET, 277); -define_syscall!(IOPRIO_GET, 278); -define_syscall!(UTIMENSAT, 279); -define_syscall!(SIGNALFD, 280); -define_syscall!(TIMERFD, 281); -define_syscall!(EVENTFD, 282); -define_syscall!(FALLOCATE, 283); -define_syscall!(TIMERFD_CREATE, 284); -define_syscall!(TIMERFD_GETTIME, 285); -define_syscall!(TIMERFD_SETTIME, 286); -define_syscall!(SIGNALFD4, 287); -define_syscall!(EVENTFD2, 288); -define_syscall!(EPOLL_CREATE1, 289); -define_syscall!(DUP3, 290); -define_syscall!(PIPE2, 291); -define_syscall!(INOTIFY_INIT1, 292); -define_syscall!(PREADV, 293); -define_syscall!(PWRITEV, 294); -define_syscall!(RT_TGSIGQUEUEINFO, 295); -define_syscall!(PERF_EVENT_OPEN, 296); -define_syscall!(ACCEPT4, 297); -define_syscall!(RECVMMSG, 298); -define_syscall!(GETDENTS64, 299); -define_syscall!(FANOTIFY_INIT, 300); -define_syscall!(FANOTIFY_MARK, 301); -define_syscall!(PRLIMIT64, 302); -define_syscall!(NAME_TO_HANDLE_AT, 303); -define_syscall!(OPEN_BY_HANDLE_AT, 304); -define_syscall!(CLOCK_ADJTIME, 305); -define_syscall!(SYNCFS, 306); -define_syscall!(SENDMMSG, 307); -define_syscall!(SETNS, 308); -define_syscall!(PROCESS_VM_READV, 309); -define_syscall!(PROCESS_VM_WRITEV, 310); -define_syscall!(KCMP, 311); -define_syscall!(FINIT_MODULE, 312); -define_syscall!(SCHED_SETATTR, 313); -define_syscall!(SCHED_GETATTR, 314); -define_syscall!(RENAMEAT2, 315); -define_syscall!(SECCOMP, 316); -define_syscall!(GETRANDOM, 317); -define_syscall!(MEMFD_CREATE, 318); -define_syscall!(BPF, 319); -define_syscall!(EXECVEAT, 320); -define_syscall!(USERFAULTFD, 321); -define_syscall!(MEMBARRIER, 322); -define_syscall!(MLOCK2, 323); -define_syscall!(COPY_FILE_RANGE, 324); -define_syscall!(PREADV2, 325); -define_syscall!(PWRITEV2, 326); -define_syscall!(PKEY_MPROTECT, 327); -define_syscall!(PKEY_ALLOC, 328); -define_syscall!(PKEY_FREE, 329); -define_syscall!(STATX, 330); -define_syscall!(RSEQ, 331); -define_syscall!(IO_PGETEVENTS, 332); +define_syscall!(SYSCALL, 0); +define_syscall!(EXIT, 1); +define_syscall!(FORK, 2); +define_syscall!(READ, 3); +define_syscall!(WRITE, 4); +define_syscall!(OPEN, 5); +define_syscall!(CLOSE, 6); +define_syscall!(WAITPID, 7); +define_syscall!(CREAT, 8); +define_syscall!(LINK, 9); +define_syscall!(UNLINK, 10); +define_syscall!(EXECVE, 11); +define_syscall!(CHDIR, 12); +define_syscall!(TIME, 13); +define_syscall!(MKNOD, 14); +define_syscall!(CHMOD, 15); +define_syscall!(LCHOWN, 16); +define_syscall!(BREAK, 17); +define_syscall!(UNUSED18, 18); +define_syscall!(LSEEK, 19); +define_syscall!(GETPID, 20); +define_syscall!(MOUNT, 21); +define_syscall!(UMOUNT, 22); +define_syscall!(SETUID, 23); +define_syscall!(GETUID, 24); +define_syscall!(STIME, 25); +define_syscall!(PTRACE, 26); +define_syscall!(ALARM, 27); +define_syscall!(UNUSED28, 28); +define_syscall!(PAUSE, 29); +define_syscall!(UTIME, 30); +define_syscall!(STTY, 31); +define_syscall!(GTTY, 32); +define_syscall!(ACCESS, 33); +define_syscall!(NICE, 34); +define_syscall!(FTIME, 35); +define_syscall!(SYNC, 36); +define_syscall!(KILL, 37); +define_syscall!(RENAME, 38); +define_syscall!(MKDIR, 39); +define_syscall!(RMDIR, 40); +define_syscall!(DUP, 41); +define_syscall!(PIPE, 42); +define_syscall!(TIMES, 43); +define_syscall!(PROF, 44); +define_syscall!(BRK, 45); +define_syscall!(SETGID, 46); +define_syscall!(GETGID, 47); +define_syscall!(SIGNAL, 48); +define_syscall!(GETEUID, 49); +define_syscall!(GETEGID, 50); +define_syscall!(ACCT, 51); +define_syscall!(UMOUNT2, 52); +define_syscall!(LOCK, 53); +define_syscall!(IOCTL, 54); +define_syscall!(FCNTL, 55); +define_syscall!(MPX, 56); +define_syscall!(SETPGID, 57); +define_syscall!(ULIMIT, 58); +define_syscall!(UNUSED59, 59); +define_syscall!(UMASK, 60); +define_syscall!(CHROOT, 61); +define_syscall!(USTAT, 62); +define_syscall!(DUP2, 63); +define_syscall!(GETPPID, 64); +define_syscall!(GETPGRP, 65); +define_syscall!(SETSID, 66); +define_syscall!(SIGACTION, 67); +define_syscall!(SGETMASK, 68); +define_syscall!(SSETMASK, 69); +define_syscall!(SETREUID, 70); +define_syscall!(SETREGID, 71); +define_syscall!(SIGSUSPEND, 72); +define_syscall!(SIGPENDING, 73); +define_syscall!(SETHOSTNAME, 74); +define_syscall!(SETRLIMIT, 75); +define_syscall!(GETRLIMIT, 76); +define_syscall!(GETRUSAGE, 77); +define_syscall!(GETTIMEOFDAY, 78); +define_syscall!(SETTIMEOFDAY, 79); +define_syscall!(GETGROUPS, 80); +define_syscall!(SETGROUPS, 81); +define_syscall!(RESERVED82, 82); +define_syscall!(SYMLINK, 83); +define_syscall!(UNUSED84, 84); +define_syscall!(READLINK, 85); +define_syscall!(USELIB, 86); +define_syscall!(SWAPON, 87); +define_syscall!(REBOOT, 88); +define_syscall!(READDIR, 89); +define_syscall!(MMAP, 90); +define_syscall!(MUNMAP, 91); +define_syscall!(TRUNCATE, 92); +define_syscall!(FTRUNCATE, 93); +define_syscall!(FCHMOD, 94); +define_syscall!(FCHOWN, 95); +define_syscall!(GETPRIORITY, 96); +define_syscall!(SETPRIORITY, 97); +define_syscall!(PROFIL, 98); +define_syscall!(STATFS, 99); +define_syscall!(FSTATFS, 100); +define_syscall!(IOPERM, 101); +define_syscall!(SOCKETCALL, 102); +define_syscall!(SYSLOG, 103); +define_syscall!(SETITIMER, 104); +define_syscall!(GETITIMER, 105); +define_syscall!(STAT, 106); +define_syscall!(LSTAT, 107); +define_syscall!(FSTAT, 108); +define_syscall!(UNUSED109, 109); +define_syscall!(IOPL, 110); +define_syscall!(VHANGUP, 111); +define_syscall!(IDLE, 112); +define_syscall!(VM86, 113); +define_syscall!(WAIT4, 114); +define_syscall!(SWAPOFF, 115); +define_syscall!(SYSINFO, 116); +define_syscall!(IPC, 117); +define_syscall!(FSYNC, 118); +define_syscall!(SIGRETURN, 119); +define_syscall!(CLONE, 120); +define_syscall!(SETDOMAINNAME, 121); +define_syscall!(UNAME, 122); +define_syscall!(MODIFY_LDT, 123); +define_syscall!(ADJTIMEX, 124); +define_syscall!(MPROTECT, 125); +define_syscall!(SIGPROCMASK, 126); +define_syscall!(CREATE_MODULE, 127); +define_syscall!(INIT_MODULE, 128); +define_syscall!(DELETE_MODULE, 129); +define_syscall!(GET_KERNEL_SYMS, 130); +define_syscall!(QUOTACTL, 131); +define_syscall!(GETPGID, 132); +define_syscall!(FCHDIR, 133); +define_syscall!(BDFLUSH, 134); +define_syscall!(SYSFS, 135); +define_syscall!(PERSONALITY, 136); +define_syscall!(AFS_SYSCALL, 137); +define_syscall!(SETFSUID, 138); +define_syscall!(SETFSGID, 139); +define_syscall!(_LLSEEK, 140); +define_syscall!(GETDENTS, 141); +define_syscall!(_NEWSELECT, 142); +define_syscall!(FLOCK, 143); +define_syscall!(MSYNC, 144); +define_syscall!(READV, 145); +define_syscall!(WRITEV, 146); +define_syscall!(CACHEFLUSH, 147); +define_syscall!(CACHECTL, 148); +define_syscall!(SYSMIPS, 149); +define_syscall!(UNUSED150, 150); +define_syscall!(GETSID, 151); +define_syscall!(FDATASYNC, 152); +define_syscall!(_SYSCTL, 153); +define_syscall!(MLOCK, 154); +define_syscall!(MUNLOCK, 155); +define_syscall!(MLOCKALL, 156); +define_syscall!(MUNLOCKALL, 157); +define_syscall!(SCHED_SETPARAM, 158); +define_syscall!(SCHED_GETPARAM, 159); +define_syscall!(SCHED_SETSCHEDULER, 160); +define_syscall!(SCHED_GETSCHEDULER, 161); +define_syscall!(SCHED_YIELD, 162); +define_syscall!(SCHED_GET_PRIORITY_MAX, 163); +define_syscall!(SCHED_GET_PRIORITY_MIN, 164); +define_syscall!(SCHED_RR_GET_INTERVAL, 165); +define_syscall!(NANOSLEEP, 166); +define_syscall!(MREMAP, 167); +define_syscall!(ACCEPT, 168); +define_syscall!(BIND, 169); +define_syscall!(CONNECT, 170); +define_syscall!(GETPEERNAME, 171); +define_syscall!(GETSOCKNAME, 172); +define_syscall!(GETSOCKOPT, 173); +define_syscall!(LISTEN, 174); +define_syscall!(RECV, 175); +define_syscall!(RECVFROM, 176); +define_syscall!(RECVMSG, 177); +define_syscall!(SEND, 178); +define_syscall!(SENDMSG, 179); +define_syscall!(SENDTO, 180); +define_syscall!(SETSOCKOPT, 181); +define_syscall!(SHUTDOWN, 182); +define_syscall!(SOCKET, 183); +define_syscall!(SOCKETPAIR, 184); +define_syscall!(SETRESUID, 185); +define_syscall!(GETRESUID, 186); +define_syscall!(QUERY_MODULE, 187); +define_syscall!(POLL, 188); +define_syscall!(NFSSERVCTL, 189); +define_syscall!(SETRESGID, 190); +define_syscall!(GETRESGID, 191); +define_syscall!(PRCTL, 192); +define_syscall!(RT_SIGRETURN, 193); +define_syscall!(RT_SIGACTION, 194); +define_syscall!(RT_SIGPROCMASK, 195); +define_syscall!(RT_SIGPENDING, 196); +define_syscall!(RT_SIGTIMEDWAIT, 197); +define_syscall!(RT_SIGQUEUEINFO, 198); +define_syscall!(RT_SIGSUSPEND, 199); +define_syscall!(PREAD64, 200); +define_syscall!(PWRITE64, 201); +define_syscall!(CHOWN, 202); +define_syscall!(GETCWD, 203); +define_syscall!(CAPGET, 204); +define_syscall!(CAPSET, 205); +define_syscall!(SIGALTSTACK, 206); +define_syscall!(SENDFILE, 207); +define_syscall!(GETPMSG, 208); +define_syscall!(PUTPMSG, 209); +define_syscall!(MMAP2, 210); +define_syscall!(TRUNCATE64, 211); +define_syscall!(FTRUNCATE64, 212); +define_syscall!(STAT64, 213); +define_syscall!(LSTAT64, 214); +define_syscall!(FSTAT64, 215); +define_syscall!(PIVOT_ROOT, 216); +define_syscall!(MINCORE, 217); +define_syscall!(MADVISE, 218); +define_syscall!(GETDENTS64, 219); +define_syscall!(FCNTL64, 220); +define_syscall!(RESERVED221, 221); +define_syscall!(GETTID, 222); +define_syscall!(READAHEAD, 223); +define_syscall!(SETXATTR, 224); +define_syscall!(LSETXATTR, 225); +define_syscall!(FSETXATTR, 226); +define_syscall!(GETXATTR, 227); +define_syscall!(LGETXATTR, 228); +define_syscall!(FGETXATTR, 229); +define_syscall!(LISTXATTR, 230); +define_syscall!(LLISTXATTR, 231); +define_syscall!(FLISTXATTR, 232); +define_syscall!(REMOVEXATTR, 233); +define_syscall!(LREMOVEXATTR, 234); +define_syscall!(FREMOVEXATTR, 235); +define_syscall!(TKILL, 236); +define_syscall!(SENDFILE64, 237); +define_syscall!(FUTEX, 238); +define_syscall!(SCHED_SETAFFINITY, 239); +define_syscall!(SCHED_GETAFFINITY, 240); +define_syscall!(IO_SETUP, 241); +define_syscall!(IO_DESTROY, 242); +define_syscall!(IO_GETEVENTS, 243); +define_syscall!(IO_SUBMIT, 244); +define_syscall!(IO_CANCEL, 245); +define_syscall!(EXIT_GROUP, 246); +define_syscall!(LOOKUP_DCOOKIE, 247); +define_syscall!(EPOLL_CREATE, 248); +define_syscall!(EPOLL_CTL, 249); +define_syscall!(EPOLL_WAIT, 250); +define_syscall!(REMAP_FILE_PAGES, 251); +define_syscall!(SET_TID_ADDRESS, 252); +define_syscall!(RESTART_SYSCALL, 253); +define_syscall!(FADVISE64, 254); +define_syscall!(STATFS64, 255); +define_syscall!(FSTATFS64, 256); +define_syscall!(TIMER_CREATE, 257); +define_syscall!(TIMER_SETTIME, 258); +define_syscall!(TIMER_GETTIME, 259); +define_syscall!(TIMER_GETOVERRUN, 260); +define_syscall!(TIMER_DELETE, 261); +define_syscall!(CLOCK_SETTIME, 262); +define_syscall!(CLOCK_GETTIME, 263); +define_syscall!(CLOCK_GETRES, 264); +define_syscall!(CLOCK_NANOSLEEP, 265); +define_syscall!(TGKILL, 266); +define_syscall!(UTIMES, 267); +define_syscall!(MBIND, 268); +define_syscall!(GET_MEMPOLICY, 269); +define_syscall!(SET_MEMPOLICY, 270); +define_syscall!(MQ_OPEN, 271); +define_syscall!(MQ_UNLINK, 272); +define_syscall!(MQ_TIMEDSEND, 273); +define_syscall!(MQ_TIMEDRECEIVE, 274); +define_syscall!(MQ_NOTIFY, 275); +define_syscall!(MQ_GETSETATTR, 276); +define_syscall!(VSERVER, 277); +define_syscall!(WAITID, 278); +define_syscall!(SYS_SETALTROOT, 279); +define_syscall!(ADD_KEY, 280); +define_syscall!(REQUEST_KEY, 281); +define_syscall!(KEYCTL, 282); +define_syscall!(SET_THREAD_AREA, 283); +define_syscall!(INOTIFY_INIT, 284); +define_syscall!(INOTIFY_ADD_WATCH, 285); +define_syscall!(INOTIFY_RM_WATCH, 286); +define_syscall!(MIGRATE_PAGES, 287); +define_syscall!(OPENAT, 288); +define_syscall!(MKDIRAT, 289); +define_syscall!(MKNODAT, 290); +define_syscall!(FCHOWNAT, 291); +define_syscall!(FUTIMESAT, 292); +define_syscall!(FSTATAT64, 293); +define_syscall!(UNLINKAT, 294); +define_syscall!(RENAMEAT, 295); +define_syscall!(LINKAT, 296); +define_syscall!(SYMLINKAT, 297); +define_syscall!(READLINKAT, 298); +define_syscall!(FCHMODAT, 299); +define_syscall!(FACCESSAT, 300); +define_syscall!(PSELECT6, 301); +define_syscall!(PPOLL, 302); +define_syscall!(UNSHARE, 303); +define_syscall!(SPLICE, 304); +define_syscall!(SYNC_FILE_RANGE, 305); +define_syscall!(TEE, 306); +define_syscall!(VMSPLICE, 307); +define_syscall!(MOVE_PAGES, 308); +define_syscall!(SET_ROBUST_LIST, 309); +define_syscall!(GET_ROBUST_LIST, 310); +define_syscall!(KEXEC_LOAD, 311); +define_syscall!(GETCPU, 312); +define_syscall!(EPOLL_PWAIT, 313); +define_syscall!(IOPRIO_SET, 314); +define_syscall!(IOPRIO_GET, 315); +define_syscall!(UTIMENSAT, 316); +define_syscall!(SIGNALFD, 317); +define_syscall!(TIMERFD, 318); +define_syscall!(EVENTFD, 319); +define_syscall!(FALLOCATE, 320); +define_syscall!(TIMERFD_CREATE, 321); +define_syscall!(TIMERFD_GETTIME, 322); +define_syscall!(TIMERFD_SETTIME, 323); +define_syscall!(SIGNALFD4, 324); +define_syscall!(EVENTFD2, 325); +define_syscall!(EPOLL_CREATE1, 326); +define_syscall!(DUP3, 327); +define_syscall!(PIPE2, 328); +define_syscall!(INOTIFY_INIT1, 329); +define_syscall!(PREADV, 330); +define_syscall!(PWRITEV, 331); +define_syscall!(RT_TGSIGQUEUEINFO, 332); +define_syscall!(PERF_EVENT_OPEN, 333); +define_syscall!(ACCEPT4, 334); +define_syscall!(RECVMMSG, 335); +define_syscall!(FANOTIFY_INIT, 336); +define_syscall!(FANOTIFY_MARK, 337); +define_syscall!(PRLIMIT64, 338); +define_syscall!(NAME_TO_HANDLE_AT, 339); +define_syscall!(OPEN_BY_HANDLE_AT, 340); +define_syscall!(CLOCK_ADJTIME, 341); +define_syscall!(SYNCFS, 342); +define_syscall!(SENDMMSG, 343); +define_syscall!(SETNS, 344); +define_syscall!(PROCESS_VM_READV, 345); +define_syscall!(PROCESS_VM_WRITEV, 346); +define_syscall!(KCMP, 347); +define_syscall!(FINIT_MODULE, 348); +define_syscall!(SCHED_SETATTR, 349); +define_syscall!(SCHED_GETATTR, 350); +define_syscall!(RENAMEAT2, 351); +define_syscall!(SECCOMP, 352); +define_syscall!(GETRANDOM, 353); +define_syscall!(MEMFD_CREATE, 354); +define_syscall!(BPF, 355); +define_syscall!(EXECVEAT, 356); +define_syscall!(USERFAULTFD, 357); +define_syscall!(MEMBARRIER, 358); +define_syscall!(MLOCK2, 359); +define_syscall!(COPY_FILE_RANGE, 360); +define_syscall!(PREADV2, 361); +define_syscall!(PWRITEV2, 362); +define_syscall!(PKEY_MPROTECT, 363); +define_syscall!(PKEY_ALLOC, 364); +define_syscall!(PKEY_FREE, 365); +define_syscall!(STATX, 366); +define_syscall!(RSEQ, 367); +define_syscall!(IO_PGETEVENTS, 368); + +// non-existent syscalls, will not be called or matched +pub const SYS_NEWFSTATAT: usize = 0; // custom temporary syscall pub const SYS_MAP_PCI_DEVICE: usize = 999; diff --git a/user b/user index 23cfbb6..a2985b6 160000 --- a/user +++ b/user @@ -1 +1 @@ -Subproject commit 23cfbb6565377ee88ad0cec3c1fcd3a090ee88c6 +Subproject commit a2985b6e80b14996bb7c767d2c202d237e82aa0d From ecdbc9fd7a1dd56927e9ae0f239e2940fc7d3b52 Mon Sep 17 00:00:00 2001 From: Harry Chen Date: Sun, 7 Apr 2019 18:36:29 +0800 Subject: [PATCH 64/85] Switch to uart2 on malta to get interrupts (not working) Signed-off-by: Harry Chen --- kernel/Makefile | 8 +++++++- kernel/src/arch/mipsel/board/malta/mod.rs | 10 +++++++++- kernel/src/arch/mipsel/interrupt.rs | 4 ++-- 3 files changed, 18 insertions(+), 4 deletions(-) diff --git a/kernel/Makefile b/kernel/Makefile index 9466a82..d7d1df1 100644 --- a/kernel/Makefile +++ b/kernel/Makefile @@ -134,7 +134,13 @@ qemu_opts += \ -kernel $(kernel_img) else ifeq ($(arch), mipsel) -ifeq ($(board), $(filter $(board), malta mipssim)) +ifeq ($(board), malta) +qemu_opts += \ + -machine $(board) \ + -serial null -serial null -serial mon:stdio \ + -kernel $(kernel_img) +endif +ifeq ($(board), mipssim) qemu_opts += \ -machine $(board) \ -serial mon:stdio \ diff --git a/kernel/src/arch/mipsel/board/malta/mod.rs b/kernel/src/arch/mipsel/board/malta/mod.rs index 0c594ef..67d5a8f 100644 --- a/kernel/src/arch/mipsel/board/malta/mod.rs +++ b/kernel/src/arch/mipsel/board/malta/mod.rs @@ -1,5 +1,6 @@ use once::*; use alloc::string::String; +use mips::registers::cp0; #[path = "../../../../drivers/serial/16550_reg.rs"] pub mod serial; @@ -12,7 +13,14 @@ pub mod consts; /// Initialize serial port first pub fn init_serial_early() { assert_has_not_been_called!("board::init must be called only once"); - serial::init(0xb80003f8); + // initialize serial driver + serial::init(0xbf000900); + // Enable serial interrupt + unsafe { + let mut status = cp0::status::read(); + status.enable_hard_int2(); + cp0::status::write(status); + } println!("Hello QEMU Malta!"); } diff --git a/kernel/src/arch/mipsel/interrupt.rs b/kernel/src/arch/mipsel/interrupt.rs index d85539e..19c0aad 100644 --- a/kernel/src/arch/mipsel/interrupt.rs +++ b/kernel/src/arch/mipsel/interrupt.rs @@ -75,7 +75,7 @@ pub extern fn rust_trap(tf: &mut TrapFrame) { fn interrupt_dispatcher(tf: &mut TrapFrame) { let pint = tf.cause.pending_interrupt(); - trace!(" Interrupt {:?} ", tf.cause.pending_interrupt()); + trace!(" Interrupt {:08b} ", pint); if (pint & 0b100_000_00) != 0 { timer(); } else if (pint & 0b011_111_00) != 0 { @@ -86,7 +86,6 @@ fn interrupt_dispatcher(tf: &mut TrapFrame) { } fn external() { - // TODO // true means handled, false otherwise let handlers = [try_process_serial, try_process_drivers]; for handler in handlers.iter() { @@ -99,6 +98,7 @@ fn external() { fn try_process_serial() -> bool { match super::io::getchar_option() { Some(ch) => { + trace!("Get char {} from serial", ch); crate::trap::serial(ch); true } From 706f7e4e9ade8f749198a4e5d1bbfdf96ded48b1 Mon Sep 17 00:00:00 2001 From: Harry Chen Date: Sun, 7 Apr 2019 18:52:10 +0800 Subject: [PATCH 65/85] Fix UART controller for malta, now input works! Signed-off-by: Harry Chen --- kernel/src/arch/mipsel/board/malta/mod.rs | 2 +- kernel/src/arch/mipsel/interrupt.rs | 6 +- kernel/src/drivers/serial/ti_16c550c.rs | 110 ++++++++++++++++++++++ 3 files changed, 115 insertions(+), 3 deletions(-) create mode 100644 kernel/src/drivers/serial/ti_16c550c.rs diff --git a/kernel/src/arch/mipsel/board/malta/mod.rs b/kernel/src/arch/mipsel/board/malta/mod.rs index 67d5a8f..1e8251d 100644 --- a/kernel/src/arch/mipsel/board/malta/mod.rs +++ b/kernel/src/arch/mipsel/board/malta/mod.rs @@ -2,7 +2,7 @@ use once::*; use alloc::string::String; use mips::registers::cp0; -#[path = "../../../../drivers/serial/16550_reg.rs"] +#[path = "../../../../drivers/serial/ti_16c550c.rs"] pub mod serial; #[path = "../../../../drivers/gpu/fb.rs"] pub mod fb; diff --git a/kernel/src/arch/mipsel/interrupt.rs b/kernel/src/arch/mipsel/interrupt.rs index 19c0aad..36176b9 100644 --- a/kernel/src/arch/mipsel/interrupt.rs +++ b/kernel/src/arch/mipsel/interrupt.rs @@ -132,13 +132,15 @@ fn syscall(tf: &mut TrapFrame) { let arguments = [tf.a0, tf.a1, tf.a2, tf.a3, tf.t0, tf.t1]; trace!("MIPS syscall {} invoked with {:?}", tf.v0, arguments); - let ret = crate::syscall::syscall(tf.v0, arguments, tf); - let ret = tf.v0 as isize; + let ret = crate::syscall::syscall(tf.v0, arguments, tf) as isize; // comply with mips n32 abi, always return a positive value // https://git.musl-libc.org/cgit/musl/tree/arch/mipsn32/syscall_arch.h if (ret < 0) { tf.v0 = (-ret) as usize; tf.a3 = 1; + } else { + tf.v0 = ret as usize; + tf.a3 = 0; } } diff --git a/kernel/src/drivers/serial/ti_16c550c.rs b/kernel/src/drivers/serial/ti_16c550c.rs new file mode 100644 index 0000000..0ee544e --- /dev/null +++ b/kernel/src/drivers/serial/ti_16c550c.rs @@ -0,0 +1,110 @@ +//! TI 16c550c serial adapter driver for malta board + +#![allow(dead_code)] + +use core::fmt::{Write, Result, Arguments}; +use core::ptr::{read_volatile, write_volatile}; +use spin::Mutex; + +pub struct SerialPort { + base: usize +} + +impl SerialPort { + fn new() -> SerialPort { + SerialPort { + base: 0 + } + } + + pub fn init(&mut self, base: usize) { + self.base = base; + // Turn off the FIFO + // write(self.base + COM_FCR, 0 as u8); + // Set speed; requires DLAB latch + // write(self.base + COM_LCR, COM_LCR_DLAB); + // write(self.base + COM_DLL, (115200 / 9600) as u8); + // write(self.base + COM_DLM, 0 as u8); + + // 8 data bits, 1 stop bit, parity off; turn off DLAB latch + // write(self.base + COM_LCR, COM_LCR_WLEN8 & !COM_LCR_DLAB); + + // No modem controls + // write(self.base + COM_MCR, 0 as u8); + // Enable rcv interrupts + write(self.base + COM_INT_EN, 0x1); + } + + /// non-blocking version of putchar() + pub fn putchar(&mut self, c: u8) { + write(self.base + COM_TX, c); + } + + /// blocking version of getchar() + pub fn getchar(&mut self) -> char { + loop { + if (read::(self.base + COM_LSR) & 0x01) == 0 { + break; + } + } + let c = read::(self.base + COM_RX); + match c { + 255 => '\0', // null + c => c as char, + } + } + + /// non-blocking version of getchar() + pub fn getchar_option(&mut self) -> Option { + match read::(self.base + COM_LSR) & 0x01 { + 0 => None, + _ => Some(read::(self.base + COM_RX) as u8 as char), + } + } + + pub fn putfmt(&mut self, fmt: Arguments) { + self.write_fmt(fmt).unwrap(); + } + +} + +impl Write for SerialPort { + fn write_str(&mut self, s: &str) -> Result { + for c in s.bytes() { + if c == 127 { + self.putchar(8); + self.putchar(b' '); + self.putchar(8); + } else { + self.putchar(c); + } + } + Ok(()) + } +} + +fn write(addr: usize, content: T) { + let cell = (addr) as *mut T; + unsafe { write_volatile(cell, content); } +} + +fn read(addr: usize) -> T { + let cell = (addr) as *const T; + unsafe { read_volatile(cell) } +} + + +const COM_RX :usize = 0x00; // In: Receive buffer (DLAB=0) +const COM_TX :usize = 0x00; // Out: Transmit buffer (DLAB=0) +const COM_INT_EN :usize = 0x08; // In: Interrupt enable +const COM_INT_ID :usize = 0x10; // Out: Interrupt identification +const COM_LSR :usize = 0x28; // In: Line status register + + +lazy_static! { + pub static ref SERIAL_PORT: Mutex = Mutex::new(SerialPort::new()); +} + +pub fn init(base: usize) { + SERIAL_PORT.lock().init(base); +} From 12598a07bfa319d5976d534eefda71fd5d38b6a7 Mon Sep 17 00:00:00 2001 From: Harry Chen Date: Sun, 7 Apr 2019 18:59:09 +0800 Subject: [PATCH 66/85] Update to latest user app Signed-off-by: Harry Chen --- user | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/user b/user index a2985b6..215b8c5 160000 --- a/user +++ b/user @@ -1 +1 @@ -Subproject commit a2985b6e80b14996bb7c767d2c202d237e82aa0d +Subproject commit 215b8c52b33ef5f31935fe6be1abec57b64d8866 From 684a2c5dd8642a6c1426a41b56dad5c4f35e8bfe Mon Sep 17 00:00:00 2001 From: Yuhao Zhou Date: Mon, 8 Apr 2019 01:00:26 +0800 Subject: [PATCH 67/85] Fix syscall return register. --- kernel/Makefile | 2 +- kernel/src/arch/mipsel/context.rs | 8 ++++---- kernel/src/arch/mipsel/interrupt.rs | 6 ++++-- 3 files changed, 9 insertions(+), 7 deletions(-) diff --git a/kernel/Makefile b/kernel/Makefile index d7d1df1..2db02a5 100644 --- a/kernel/Makefile +++ b/kernel/Makefile @@ -200,7 +200,7 @@ prefix := riscv64-unknown-elf- else ifeq ($(arch), riscv64) prefix := riscv64-unknown-elf- else ifeq ($(arch), mipsel) -prefix ?= mipsel-linux-gnu- +prefix ?= mipsel-linux-musln32- else ifeq ($(arch), aarch64) prefix ?= aarch64-none-elf- ifeq (,$(shell which $(prefix)ld)) diff --git a/kernel/src/arch/mipsel/context.rs b/kernel/src/arch/mipsel/context.rs index 9227bef..3236703 100644 --- a/kernel/src/arch/mipsel/context.rs +++ b/kernel/src/arch/mipsel/context.rs @@ -174,7 +174,7 @@ impl Context { /// The stack pointer will be set to `kstack_top`. /// The SATP register will be set to `satp`. pub unsafe fn new_kernel_thread(entry: extern fn(usize) -> !, arg: usize, kstack_top: usize, satp: usize) -> Self { - trace!("New kernel thread @ {:x}, stack = {:x}", entry as usize, kstack_top); + info!("New kernel thread @ {:x}, stack = {:x}", entry as usize, kstack_top); InitStack { context: ContextData::new(satp), @@ -188,7 +188,7 @@ impl Context { /// The stack pointer of user and kernel mode will be set to `ustack_top`, `kstack_top`. /// The SATP register will be set to `satp`. pub unsafe fn new_user_thread(entry_addr: usize, ustack_top: usize, kstack_top: usize, _is32: bool, satp: usize) -> Self { - trace!("New user thread @ {:x}, stack = {:x}", entry_addr, kstack_top); + info!("New user thread @ {:x}, stack = {:x}", entry_addr, kstack_top); InitStack { context: ContextData::new(satp), @@ -207,7 +207,7 @@ impl Context { tf: { let mut tf = tf.clone(); // fork function's ret value, the new process is 0 - tf.a0 = 0; + tf.v0 = 0; tf }, }.push_at(kstack_top) @@ -227,7 +227,7 @@ impl Context { let mut tf = tf.clone(); tf.sp = ustack_top; // sp tf.v1 = tls; // tp - tf.a0 = 0; // a0 + tf.v0 = 0; // a0 tf }, }.push_at(kstack_top) diff --git a/kernel/src/arch/mipsel/interrupt.rs b/kernel/src/arch/mipsel/interrupt.rs index 36176b9..21f39f2 100644 --- a/kernel/src/arch/mipsel/interrupt.rs +++ b/kernel/src/arch/mipsel/interrupt.rs @@ -156,8 +156,10 @@ fn page_fault(tf: &mut TrapFrame) { let tlb_result = root_table.lookup(addr); match tlb_result { Ok(tlb_entry) => tlb::write_tlb_random(tlb_entry), - Err(()) => if !crate::memory::handle_page_fault(addr) { - crate::trap::error(tf); + Err(()) => { + if !crate::memory::handle_page_fault(addr) { + crate::trap::error(tf); + } } } } From df3eb0e1da2a2e94058adaa9887e2b59afa8928c Mon Sep 17 00:00:00 2001 From: Harry Chen Date: Mon, 8 Apr 2019 01:30:25 +0800 Subject: [PATCH 68/85] Add ColorConfig support to framebuffer driver Signed-off-by: Harry Chen --- kernel/src/arch/aarch64/board/raspi3/mod.rs | 6 +-- kernel/src/arch/mipsel/board/malta/mod.rs | 2 +- kernel/src/arch/mipsel/board/mipssim/mod.rs | 2 +- kernel/src/arch/mipsel/board/thinpad/mod.rs | 5 +- kernel/src/drivers/console/color.rs | 54 +++++++-------------- kernel/src/drivers/console/mod.rs | 17 ++----- kernel/src/drivers/gpu/fb.rs | 17 ++++++- 7 files changed, 46 insertions(+), 57 deletions(-) diff --git a/kernel/src/arch/aarch64/board/raspi3/mod.rs b/kernel/src/arch/aarch64/board/raspi3/mod.rs index 9b2a66b..dfd7235 100644 --- a/kernel/src/arch/aarch64/board/raspi3/mod.rs +++ b/kernel/src/arch/aarch64/board/raspi3/mod.rs @@ -12,7 +12,7 @@ pub mod mailbox; pub mod serial; pub mod timer; -use fb::FramebufferInfo; +use fb::{ColorConfig, FramebufferInfo, FramebufferResult}; pub const IO_REMAP_BASE: usize = bcm2837::consts::IO_BASE; pub const IO_REMAP_END: usize = bcm2837::consts::KERNEL_OFFSET + 0x4000_1000; @@ -47,7 +47,7 @@ pub fn probe_memory() -> Option<(usize, usize)> { None } -pub fn probe_fb_info(width: u32, height: u32, depth: u32) -> Result<(FramebufferInfo, usize), String> { +pub fn probe_fb_info(width: u32, height: u32, depth: u32) -> FramebufferResult { let (width, height) = if width == 0 || height == 0 { mailbox::framebuffer_get_physical_size()? @@ -84,5 +84,5 @@ pub fn probe_fb_info(width: u32, height: u32, depth: u32) -> Result<(Framebuffer ))?; } - Ok((info, vaddr)) + Ok((info, fb::ColorConfig::BGRA8888, vaddr)) } \ No newline at end of file diff --git a/kernel/src/arch/mipsel/board/malta/mod.rs b/kernel/src/arch/mipsel/board/malta/mod.rs index 1e8251d..c345f75 100644 --- a/kernel/src/arch/mipsel/board/malta/mod.rs +++ b/kernel/src/arch/mipsel/board/malta/mod.rs @@ -30,6 +30,6 @@ pub fn init_driver() { // timer::init(); } -pub fn probe_fb_info(_width: u32, _height: u32, _depth: u32) -> Result<(fb::FramebufferInfo, usize), String> { +pub fn probe_fb_info(_width: u32, _height: u32, _depth: u32) -> fb::FramebufferResult { Err(String::from("Framebuffer not usable on malta board")) } \ No newline at end of file diff --git a/kernel/src/arch/mipsel/board/mipssim/mod.rs b/kernel/src/arch/mipsel/board/mipssim/mod.rs index 6633d7d..4f1a4f4 100644 --- a/kernel/src/arch/mipsel/board/mipssim/mod.rs +++ b/kernel/src/arch/mipsel/board/mipssim/mod.rs @@ -22,6 +22,6 @@ pub fn init_driver() { // timer::init(); } -pub fn probe_fb_info(_width: u32, _height: u32, _depth: u32) -> Result<(fb::FramebufferInfo, usize), String> { +pub fn probe_fb_info(_width: u32, _height: u32, _depth: u32) -> fb::FramebufferResult { Err(String::from("Framebuffer not usable on mipssim board")) } \ No newline at end of file diff --git a/kernel/src/arch/mipsel/board/thinpad/mod.rs b/kernel/src/arch/mipsel/board/thinpad/mod.rs index 1ebf3d1..dc4fe8a 100644 --- a/kernel/src/arch/mipsel/board/thinpad/mod.rs +++ b/kernel/src/arch/mipsel/board/thinpad/mod.rs @@ -10,6 +10,7 @@ pub mod console; pub mod consts; use fb::FramebufferInfo; +use fb::FramebufferResult; /// Initialize serial port first pub fn init_serial_early() { @@ -24,7 +25,7 @@ pub fn init_driver() { // timer::init(); } -pub fn probe_fb_info(width: u32, height: u32, depth: u32) -> Result<(FramebufferInfo, usize), String> { +pub fn probe_fb_info(width: u32, height: u32, depth: u32) -> FramebufferResult { let fb_info = FramebufferInfo { xres: 800, yres: 600, @@ -37,5 +38,5 @@ pub fn probe_fb_info(width: u32, height: u32, depth: u32) -> Result<(Framebuffer bus_addr: 0xa2000000, screen_size: 800 * 600, }; - Ok((fb_info, 0xa2000000)) + Ok((fb_info, fb::ColorConfig::RGB332, 0xa2000000)) } \ No newline at end of file diff --git a/kernel/src/drivers/console/color.rs b/kernel/src/drivers/console/color.rs index 1936fb8..f3cde77 100644 --- a/kernel/src/drivers/console/color.rs +++ b/kernel/src/drivers/console/color.rs @@ -2,15 +2,10 @@ use crate::util::color::ConsoleColor; -pub trait FramebufferColor { - /// pack as 8-bit integer - fn pack8(&self) -> u8; - - /// pack as 16-bit integer - fn pack16(&self) -> u16; +use super::ColorConfig; - /// pack as 32-bit integer - fn pack32(&self) -> u32; +pub trait FramebufferColor { + fn pack32(&self, config: ColorConfig) -> u32; } #[repr(C)] @@ -46,39 +41,24 @@ impl From for RgbColor { impl FramebufferColor for RgbColor { #[inline] - fn pack8(&self) -> u8 { - // RGB332 - ((self.0 >> 5) << 5) | ((self.1 >> 5) << 2) | (self.2 >> 6) - } - - #[inline] - fn pack16(&self) -> u16 { - // BGR565 - ((self.0 as u16 & 0xF8) << 8) | ((self.1 as u16 & 0xFC) << 3) | (self.2 as u16 >> 3) - } - - #[inline] - fn pack32(&self) -> u32 { - // BGRA8888 - // FIXME: qemu and low version RPi use RGBA order for 24/32-bit color depth, - // but RPi3 B+ uses BGRA order for 24/32-bit color depth. - ((self.0 as u32) << 16) | ((self.1 as u32) << 8) | (self.2 as u32) + fn pack32(&self, config: ColorConfig) -> u32 { + match config { + ColorConfig::RGB332 => (((self.0 >> 5) << 5) | ((self.1 >> 5) << 2) | (self.2 >> 6)) as u32, + ColorConfig::RGB565 => (((self.0 as u16 & 0xF8) << 8) | ((self.1 as u16 & 0xFC) << 3) | (self.2 as u16 >> 3)) as u32, + // FIXME: qemu and low version RPi use RGBA order for 24/32-bit color depth, + // but RPi3 B+ uses BGRA order for 24/32-bit color depth. + ColorConfig::BGRA8888 => ((self.0 as u32) << 16) | ((self.1 as u32) << 8) | (self.2 as u32), + _ => unimplemented!() + } } } impl FramebufferColor for ConsoleColor { #[inline] - fn pack8(&self) -> u8 { - RgbColor::from(*self).pack8() - } - - #[inline] - fn pack16(&self) -> u16 { - RgbColor::from(*self).pack16() - } - - #[inline] - fn pack32(&self) -> u32 { - RgbColor::from(*self).pack32() + fn pack32(&self, config: ColorConfig) -> u32 { + match config { + ColorConfig::VgaPalette => *self as u32, + _ => RgbColor::from(*self).pack32(config), + } } } diff --git a/kernel/src/drivers/console/mod.rs b/kernel/src/drivers/console/mod.rs index 29d56be..71721aa 100644 --- a/kernel/src/drivers/console/mod.rs +++ b/kernel/src/drivers/console/mod.rs @@ -10,7 +10,7 @@ use spin::Mutex; use crate::util::escape_parser::{CharacterAttribute, EscapeParser}; -use super::fb::{ColorDepth::*, FramebufferInfo, FRAME_BUFFER}; +use super::fb::{ColorDepth::*, ColorConfig, FramebufferInfo, FRAME_BUFFER}; use self::color::FramebufferColor; use self::fonts::{Font, Font8x16}; @@ -62,17 +62,10 @@ impl ConsoleBuffer { let off_x = col * F::WIDTH; let off_y = row * F::HEIGHT; if let Some(fb) = FRAME_BUFFER.lock().as_mut() { - let (mut foreground, mut background) = match fb.color_depth { - ColorDepth8 => ( - ch.attr.foreground.pack8() as u32, - ch.attr.background.pack8() as u32, - ), - ColorDepth16 => ( - ch.attr.foreground.pack16() as u32, - ch.attr.background.pack16() as u32, - ), - ColorDepth32 => (ch.attr.foreground.pack32(), ch.attr.background.pack32()), - }; + let (mut foreground, mut background) = ( + ch.attr.foreground.pack32(fb.color_config), + ch.attr.background.pack32(fb.color_config) + ); if ch.attr.reverse { core::mem::swap(&mut foreground, &mut background); } diff --git a/kernel/src/drivers/gpu/fb.rs b/kernel/src/drivers/gpu/fb.rs index d5f7021..f34473f 100644 --- a/kernel/src/drivers/gpu/fb.rs +++ b/kernel/src/drivers/gpu/fb.rs @@ -45,6 +45,18 @@ pub enum ColorDepth { } use self::ColorDepth::*; +#[repr(u32)] +#[derive(Debug, Clone, Copy)] +pub enum ColorConfig { + RGB332, + RGB565, + BGRA8888, + VgaPalette, +} +use self::ColorConfig::*; + +pub type FramebufferResult = Result<(FramebufferInfo, ColorConfig, usize), String>; + #[repr(C)] union ColorBuffer { base_addr: usize, @@ -105,6 +117,7 @@ impl ColorBuffer { pub struct Framebuffer { pub fb_info: FramebufferInfo, pub color_depth: ColorDepth, + pub color_config: ColorConfig, buf: ColorBuffer, } @@ -113,6 +126,7 @@ impl fmt::Debug for Framebuffer { let mut f = f.debug_struct("Framebuffer"); f.field("fb_info", &self.fb_info); f.field("color_depth", &self.color_depth); + f.field("color_config", &self.color_config); f.field("base_addr", unsafe { &self.buf.base_addr }); f.finish() } @@ -125,7 +139,7 @@ impl Framebuffer { let probed_info = super::probe_fb_info(width, height, depth); match probed_info { - Ok((info, addr)) => { + Ok((info, config, addr)) => { let color_depth = match info.depth { 8 => ColorDepth8, 16 => ColorDepth16, @@ -134,6 +148,7 @@ impl Framebuffer { }; Ok(Framebuffer { buf: ColorBuffer::new(color_depth, addr, info.screen_size as usize), + color_config: config, color_depth, fb_info: info, }) From c32b0d6bee7f05464efb479740e12219d6f1d8b4 Mon Sep 17 00:00:00 2001 From: Harry Chen Date: Mon, 8 Apr 2019 02:06:30 +0800 Subject: [PATCH 69/85] Add VGA implementation for mipsel malta board Signed-off-by: Harry Chen --- kernel/src/arch/mipsel/board/malta/mod.rs | 20 +++++++++-- kernel/src/drivers/gpu/qemu_stdvga.rs | 41 +++++++++++++++++++++++ kernel/src/drivers/serial/16550_reg.rs | 12 +------ kernel/src/drivers/serial/simple_uart.rs | 12 +------ kernel/src/drivers/serial/ti_16c550c.rs | 13 +------ kernel/src/util/mod.rs | 14 ++++++++ user | 2 +- 7 files changed, 77 insertions(+), 37 deletions(-) create mode 100644 kernel/src/drivers/gpu/qemu_stdvga.rs diff --git a/kernel/src/arch/mipsel/board/malta/mod.rs b/kernel/src/arch/mipsel/board/malta/mod.rs index c345f75..c0c2cfa 100644 --- a/kernel/src/arch/mipsel/board/malta/mod.rs +++ b/kernel/src/arch/mipsel/board/malta/mod.rs @@ -4,12 +4,16 @@ use mips::registers::cp0; #[path = "../../../../drivers/serial/ti_16c550c.rs"] pub mod serial; +#[path = "../../../../drivers/gpu/qemu_stdvga.rs"] +pub mod vga; #[path = "../../../../drivers/gpu/fb.rs"] pub mod fb; #[path = "../../../../drivers/console/mod.rs"] pub mod console; pub mod consts; +use fb::FramebufferInfo; + /// Initialize serial port first pub fn init_serial_early() { assert_has_not_been_called!("board::init must be called only once"); @@ -27,9 +31,21 @@ pub fn init_serial_early() { /// Initialize other board drivers pub fn init_driver() { // TODO: add possibly more drivers - // timer::init(); + vga::init(0x92050000, 800, 600); } pub fn probe_fb_info(_width: u32, _height: u32, _depth: u32) -> fb::FramebufferResult { - Err(String::from("Framebuffer not usable on malta board")) + let fb_info = FramebufferInfo { + xres: 800, + yres: 600, + xres_virtual: 800, + yres_virtual: 600, + xoffset: 0, + yoffset: 0, + depth: 8, + pitch: 800, + bus_addr: 0x90000000, + screen_size: 800 * 600, + }; + Ok((fb_info, fb::ColorConfig::VgaPalette, 0x90000000)) } \ No newline at end of file diff --git a/kernel/src/drivers/gpu/qemu_stdvga.rs b/kernel/src/drivers/gpu/qemu_stdvga.rs new file mode 100644 index 0000000..415d01b --- /dev/null +++ b/kernel/src/drivers/gpu/qemu_stdvga.rs @@ -0,0 +1,41 @@ +//! driver for qemu stdvga (Cirrus) + +use crate::util::{read, write}; + +const VGA_MMIO_OFFSET: usize = 0x400 - 0x3c0; +const VBE_MMIO_OFFSET: usize = 0x500; + +const VGA_AR_ADDR: u16 = 0x3C0; +const VBE_DISPI_INDEX_XRES: u16 = 0x01; +const VBE_DISPI_INDEX_YRES: u16 = 0x02; +const VBE_DISPI_INDEX_BPP: u16 = 0x03; +const VBE_DISPI_INDEX_ENABLE: u16 = 0x04; + +const VGA_AR_PAS: u8 = 0x20; +const VBE_DISPI_ENABLED: u16 = 0x01; + +pub fn init(vga_base: usize, x_res: u16, y_res: u16) { + + let vga_write_io = |offset: u16, value: u8| { + write(vga_base + VGA_MMIO_OFFSET + (offset as usize), value); + }; + + let vga_write_vbe = |offset: u16, value: u16| { + write(vga_base + VBE_MMIO_OFFSET + (offset as usize) * 2, value); + }; + + let vga_read_vbe = |offset: u16| -> u16 { + read(vga_base + VBE_MMIO_OFFSET + (offset as usize) * 2) + }; + + // enable palette access + vga_write_io(VGA_AR_ADDR, VGA_AR_PAS); + // set resolution and color depth + vga_write_vbe(VBE_DISPI_INDEX_XRES, x_res); + vga_write_vbe(VBE_DISPI_INDEX_YRES, y_res); + vga_write_vbe(VBE_DISPI_INDEX_BPP, 8); + // enable vbe + let vbe_enable = vga_read_vbe(VBE_DISPI_INDEX_ENABLE) | VBE_DISPI_ENABLED; + vga_write_vbe(VBE_DISPI_INDEX_ENABLE, vbe_enable); + +} \ No newline at end of file diff --git a/kernel/src/drivers/serial/16550_reg.rs b/kernel/src/drivers/serial/16550_reg.rs index 62330c4..a86e60e 100644 --- a/kernel/src/drivers/serial/16550_reg.rs +++ b/kernel/src/drivers/serial/16550_reg.rs @@ -3,7 +3,7 @@ #![allow(dead_code)] use core::fmt::{Write, Result, Arguments}; -use core::ptr::{read_volatile, write_volatile}; +use crate::util::{read, write}; use spin::Mutex; pub struct SerialPort { @@ -83,16 +83,6 @@ impl Write for SerialPort { } } -fn write(addr: usize, content: T) { - let cell = (addr) as *mut T; - unsafe { write_volatile(cell, content); } -} - -fn read(addr: usize) -> T { - let cell = (addr) as *const T; - unsafe { read_volatile(cell) } -} - const COM_RX :usize = 0; // In: Receive buffer (DLAB=0) const COM_TX :usize = 0; // Out: Transmit buffer (DLAB=0) diff --git a/kernel/src/drivers/serial/simple_uart.rs b/kernel/src/drivers/serial/simple_uart.rs index ed7bd73..a23501a 100644 --- a/kernel/src/drivers/serial/simple_uart.rs +++ b/kernel/src/drivers/serial/simple_uart.rs @@ -1,7 +1,7 @@ //! naive serial adapter driver for thinpad use core::fmt::{Write, Result, Arguments}; -use core::ptr::{read_volatile, write_volatile}; +use crate::util::{read, write}; #[derive(Debug, Clone, Copy)] pub struct SerialPort { @@ -73,16 +73,6 @@ impl Write for SerialPort { } } -fn write(addr: usize, content: T) { - let cell = (addr) as *mut T; - unsafe { write_volatile(cell, content); } -} - -fn read(addr: usize) -> T { - let cell = (addr) as *const T; - unsafe { read_volatile(cell) } -} - pub static SERIAL_PORT: SerialPort = SerialPort { base: 0 }; diff --git a/kernel/src/drivers/serial/ti_16c550c.rs b/kernel/src/drivers/serial/ti_16c550c.rs index 0ee544e..79a47d9 100644 --- a/kernel/src/drivers/serial/ti_16c550c.rs +++ b/kernel/src/drivers/serial/ti_16c550c.rs @@ -3,8 +3,8 @@ #![allow(dead_code)] use core::fmt::{Write, Result, Arguments}; -use core::ptr::{read_volatile, write_volatile}; use spin::Mutex; +use crate::util::{read, write}; pub struct SerialPort { base: usize @@ -83,17 +83,6 @@ impl Write for SerialPort { } } -fn write(addr: usize, content: T) { - let cell = (addr) as *mut T; - unsafe { write_volatile(cell, content); } -} - -fn read(addr: usize) -> T { - let cell = (addr) as *const T; - unsafe { read_volatile(cell) } -} - - const COM_RX :usize = 0x00; // In: Receive buffer (DLAB=0) const COM_TX :usize = 0x00; // Out: Transmit buffer (DLAB=0) const COM_INT_EN :usize = 0x08; // In: Interrupt enable diff --git a/kernel/src/util/mod.rs b/kernel/src/util/mod.rs index 0c6df60..0b41620 100644 --- a/kernel/src/util/mod.rs +++ b/kernel/src/util/mod.rs @@ -1,3 +1,5 @@ +use core::ptr::{read_volatile, write_volatile}; + pub mod color; pub mod escape_parser; @@ -13,3 +15,15 @@ pub unsafe fn write_cstr(ptr: *mut u8, s: &str) { ptr.copy_from(s.as_ptr(), s.len()); ptr.add(s.len()).write(0); } + +#[inline(always)] +pub fn write(addr: usize, content: T) { + let cell = (addr) as *mut T; + unsafe { write_volatile(cell, content); } +} + +#[inline(always)] +pub fn read(addr: usize) -> T { + let cell = (addr) as *const T; + unsafe { read_volatile(cell) } +} \ No newline at end of file diff --git a/user b/user index 215b8c5..07619a4 160000 --- a/user +++ b/user @@ -1 +1 @@ -Subproject commit 215b8c52b33ef5f31935fe6be1abec57b64d8866 +Subproject commit 07619a48d4e8051766c294d9d616337869e4c1a0 From 8754a6eb15847c3e5354d5e696eb03cd75a4cb12 Mon Sep 17 00:00:00 2001 From: Harry Chen Date: Mon, 8 Apr 2019 03:03:35 +0800 Subject: [PATCH 70/85] Add PCI initialization in QEMU stdvga Signed-off-by: Harry Chen --- kernel/src/arch/mipsel/board/malta/mod.rs | 2 +- kernel/src/drivers/gpu/qemu_stdvga.rs | 38 +++++++++++++++++++++-- 2 files changed, 37 insertions(+), 3 deletions(-) diff --git a/kernel/src/arch/mipsel/board/malta/mod.rs b/kernel/src/arch/mipsel/board/malta/mod.rs index c0c2cfa..2c34e4c 100644 --- a/kernel/src/arch/mipsel/board/malta/mod.rs +++ b/kernel/src/arch/mipsel/board/malta/mod.rs @@ -31,7 +31,7 @@ pub fn init_serial_early() { /// Initialize other board drivers pub fn init_driver() { // TODO: add possibly more drivers - vga::init(0x92050000, 800, 600); + vga::init(0xb8000000, 0x92050000, 800, 600); } pub fn probe_fb_info(_width: u32, _height: u32, _depth: u32) -> fb::FramebufferResult { diff --git a/kernel/src/drivers/gpu/qemu_stdvga.rs b/kernel/src/drivers/gpu/qemu_stdvga.rs index 415d01b..bf9663f 100644 --- a/kernel/src/drivers/gpu/qemu_stdvga.rs +++ b/kernel/src/drivers/gpu/qemu_stdvga.rs @@ -14,8 +14,40 @@ const VBE_DISPI_INDEX_ENABLE: u16 = 0x04; const VGA_AR_PAS: u8 = 0x20; const VBE_DISPI_ENABLED: u16 = 0x01; -pub fn init(vga_base: usize, x_res: u16, y_res: u16) { +const PCIR_COMMAND: u8 = 0x04; +const PCIM_CMD_PORTEN: u16 = 0x0001; +const PCIM_CMD_MEMEN: u16 = 0x0002; + +fn pci_read_config(pci_base: usize, bus: u8, slot: u8, func: u8, offset: u8) -> u16 { + // enable access mechanism + let data = 0xF0 | (func << 1); + write(pci_base + 0xcf8, data); + write(pci_base + 0xcfa, bus); + // calculate port address + let addr: u16 = (0xC000 | ((slot as u16) << 8) | (offset as u16)) & 0xFFFC; + // do the actual work + read(pci_base + addr as usize) +} + +fn pci_write_config(pci_base: usize, bus: u8, slot: u8, func: u8, offset: u8, value: u16) { + // enable access mechanism + let data = 0xF0 | (func << 1); + write(pci_base + 0xcf8, data); + write(pci_base + 0xcfa, bus); + // calculate port address + let addr: u16 = (0xC000 | ((slot as u16) << 8) | (offset as u16)) & 0xFFFC; + // do the actual work + write(pci_base + addr as usize, value); +} + +pub fn init(pci_base: usize, vga_base: usize, x_res: u16, y_res: u16) { + + // enable PCI MMIO + let pci_state = pci_read_config(pci_base, 0x00, 0x12, 0x00, PCIR_COMMAND); + pci_write_config(pci_base, 0x00, 0x12, 0x00, PCIR_COMMAND, pci_state | PCIM_CMD_PORTEN | PCIM_CMD_MEMEN); + + // vga operations let vga_write_io = |offset: u16, value: u8| { write(vga_base + VGA_MMIO_OFFSET + (offset as usize), value); }; @@ -38,4 +70,6 @@ pub fn init(vga_base: usize, x_res: u16, y_res: u16) { let vbe_enable = vga_read_vbe(VBE_DISPI_INDEX_ENABLE) | VBE_DISPI_ENABLED; vga_write_vbe(VBE_DISPI_INDEX_ENABLE, vbe_enable); -} \ No newline at end of file + println!("QEMU STDVGA driver initialized @ {:x}", vga_base); + +} From a57a22a26b91cbf2da64fca19b74a241d07019d5 Mon Sep 17 00:00:00 2001 From: Harry Chen Date: Mon, 8 Apr 2019 03:18:31 +0800 Subject: [PATCH 71/85] Fix VGA initialization with correct PCI address Signed-off-by: Harry Chen --- kernel/src/arch/mipsel/board/malta/mod.rs | 6 ++--- kernel/src/drivers/gpu/qemu_stdvga.rs | 30 +++++++++-------------- 2 files changed, 15 insertions(+), 21 deletions(-) diff --git a/kernel/src/arch/mipsel/board/malta/mod.rs b/kernel/src/arch/mipsel/board/malta/mod.rs index 2c34e4c..2681bd3 100644 --- a/kernel/src/arch/mipsel/board/malta/mod.rs +++ b/kernel/src/arch/mipsel/board/malta/mod.rs @@ -31,7 +31,7 @@ pub fn init_serial_early() { /// Initialize other board drivers pub fn init_driver() { // TODO: add possibly more drivers - vga::init(0xb8000000, 0x92050000, 800, 600); + vga::init(0xb8000000, 0xb2050000, 800, 600); } pub fn probe_fb_info(_width: u32, _height: u32, _depth: u32) -> fb::FramebufferResult { @@ -44,8 +44,8 @@ pub fn probe_fb_info(_width: u32, _height: u32, _depth: u32) -> fb::FramebufferR yoffset: 0, depth: 8, pitch: 800, - bus_addr: 0x90000000, + bus_addr: 0xb0000000, screen_size: 800 * 600, }; - Ok((fb_info, fb::ColorConfig::VgaPalette, 0x90000000)) + Ok((fb_info, fb::ColorConfig::VgaPalette, 0xb0000000)) } \ No newline at end of file diff --git a/kernel/src/drivers/gpu/qemu_stdvga.rs b/kernel/src/drivers/gpu/qemu_stdvga.rs index bf9663f..31c1614 100644 --- a/kernel/src/drivers/gpu/qemu_stdvga.rs +++ b/kernel/src/drivers/gpu/qemu_stdvga.rs @@ -15,30 +15,24 @@ const VGA_AR_PAS: u8 = 0x20; const VBE_DISPI_ENABLED: u16 = 0x01; const PCIR_COMMAND: u8 = 0x04; -const PCIM_CMD_PORTEN: u16 = 0x0001; -const PCIM_CMD_MEMEN: u16 = 0x0002; +const PCIM_CMD_PORTEN: u32 = 0x0001; +const PCIM_CMD_MEMEN: u32 = 0x0002; -fn pci_read_config(pci_base: usize, bus: u8, slot: u8, func: u8, offset: u8) -> u16 { - // enable access mechanism - let data = 0xF0 | (func << 1); - write(pci_base + 0xcf8, data); - write(pci_base + 0xcfa, bus); - // calculate port address - let addr: u16 = (0xC000 | ((slot as u16) << 8) | (offset as u16)) & 0xFFFC; +fn pci_read_config(pci_base: usize, bus: u8, slot: u8, func: u8, offset: u8) -> u32 { + // write config address + let address = (1 << 31) | ((bus as u32) << 16) | ((slot as u32) << 11) | ((func as u32) << 8) | (offset as u32); + write(pci_base + 0xcf8, address); // do the actual work - read(pci_base + addr as usize) + read(pci_base + 0xcfc) } -fn pci_write_config(pci_base: usize, bus: u8, slot: u8, func: u8, offset: u8, value: u16) { - // enable access mechanism - let data = 0xF0 | (func << 1); - write(pci_base + 0xcf8, data); - write(pci_base + 0xcfa, bus); - // calculate port address - let addr: u16 = (0xC000 | ((slot as u16) << 8) | (offset as u16)) & 0xFFFC; +fn pci_write_config(pci_base: usize, bus: u8, slot: u8, func: u8, offset: u8, value: u32) { + // write config address + let address = (1 << 31) | ((bus as u32) << 16) | ((slot as u32) << 11) | ((func as u32) << 8) | (offset as u32); + write(pci_base + 0xcf8, address); // do the actual work - write(pci_base + addr as usize, value); + write(pci_base + 0xcfc, value) } pub fn init(pci_base: usize, vga_base: usize, x_res: u16, y_res: u16) { From 7e3d26ce6be3b944f98f5359cf2b1a1806f75ff7 Mon Sep 17 00:00:00 2001 From: Harry Chen Date: Mon, 8 Apr 2019 03:59:42 +0800 Subject: [PATCH 72/85] Add debug output for qemu vga driver, still not working... Signed-off-by: Harry Chen --- kernel/src/drivers/gpu/qemu_stdvga.rs | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/kernel/src/drivers/gpu/qemu_stdvga.rs b/kernel/src/drivers/gpu/qemu_stdvga.rs index 31c1614..63a3c21 100644 --- a/kernel/src/drivers/gpu/qemu_stdvga.rs +++ b/kernel/src/drivers/gpu/qemu_stdvga.rs @@ -22,6 +22,7 @@ const PCIM_CMD_MEMEN: u32 = 0x0002; fn pci_read_config(pci_base: usize, bus: u8, slot: u8, func: u8, offset: u8) -> u32 { // write config address let address = (1 << 31) | ((bus as u32) << 16) | ((slot as u32) << 11) | ((func as u32) << 8) | (offset as u32); + println!("Address: {:08x}", address); write(pci_base + 0xcf8, address); // do the actual work read(pci_base + 0xcfc) @@ -38,9 +39,14 @@ fn pci_write_config(pci_base: usize, bus: u8, slot: u8, func: u8, offset: u8, va pub fn init(pci_base: usize, vga_base: usize, x_res: u16, y_res: u16) { // enable PCI MMIO + let pci_vendor = pci_read_config(pci_base, 0x00, 0x12, 0x00, 0x0); + println!("PCI Device ID: {:08x}", pci_vendor); + let pci_state = pci_read_config(pci_base, 0x00, 0x12, 0x00, PCIR_COMMAND); + println!("PCI Config Status: {:08x}", pci_state); pci_write_config(pci_base, 0x00, 0x12, 0x00, PCIR_COMMAND, pci_state | PCIM_CMD_PORTEN | PCIM_CMD_MEMEN); + // vga operations let vga_write_io = |offset: u16, value: u8| { write(vga_base + VGA_MMIO_OFFSET + (offset as usize), value); @@ -61,8 +67,9 @@ pub fn init(pci_base: usize, vga_base: usize, x_res: u16, y_res: u16) { vga_write_vbe(VBE_DISPI_INDEX_YRES, y_res); vga_write_vbe(VBE_DISPI_INDEX_BPP, 8); // enable vbe - let vbe_enable = vga_read_vbe(VBE_DISPI_INDEX_ENABLE) | VBE_DISPI_ENABLED; - vga_write_vbe(VBE_DISPI_INDEX_ENABLE, vbe_enable); + let vbe_enable = vga_read_vbe(VBE_DISPI_INDEX_ENABLE); + println!("VBE Status: {:04x}", vbe_enable); + vga_write_vbe(VBE_DISPI_INDEX_ENABLE, vbe_enable | VBE_DISPI_ENABLED); println!("QEMU STDVGA driver initialized @ {:x}", vga_base); From b6aa9858d3785b85bba8f826d11029a9be7a1e31 Mon Sep 17 00:00:00 2001 From: Yuhao Zhou Date: Mon, 8 Apr 2019 04:47:36 +0800 Subject: [PATCH 73/85] Fix return register in sys_clone. --- kernel/Cargo.lock | 2 +- kernel/src/arch/mipsel/context.rs | 5 +++-- kernel/src/arch/mipsel/interrupt.rs | 7 ++++++- 3 files changed, 10 insertions(+), 4 deletions(-) diff --git a/kernel/Cargo.lock b/kernel/Cargo.lock index 18c5a5e..c89c9d5 100644 --- a/kernel/Cargo.lock +++ b/kernel/Cargo.lock @@ -230,7 +230,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "mips" version = "0.1.0" -source = "git+https://github.com/Harry-Chen/rust-mips#1f3df9589869670621baa863b87a3444d80f08a6" +source = "git+https://github.com/Harry-Chen/rust-mips#7410a6aa107fce681378e7850c03f9b6befec2d2" dependencies = [ "bit_field 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/kernel/src/arch/mipsel/context.rs b/kernel/src/arch/mipsel/context.rs index 3236703..4dfdad9 100644 --- a/kernel/src/arch/mipsel/context.rs +++ b/kernel/src/arch/mipsel/context.rs @@ -1,4 +1,5 @@ use mips::registers::cp0; +use mips::tlb; /// Saved registers on a trap. #[derive(Clone)] @@ -226,8 +227,8 @@ impl Context { tf: { let mut tf = tf.clone(); tf.sp = ustack_top; // sp - tf.v1 = tls; // tp - tf.v0 = 0; // a0 + tf.v1 = tls; + tf.a0 = 0; // return value tf }, }.push_at(kstack_top) diff --git a/kernel/src/arch/mipsel/interrupt.rs b/kernel/src/arch/mipsel/interrupt.rs index 21f39f2..5a64411 100644 --- a/kernel/src/arch/mipsel/interrupt.rs +++ b/kernel/src/arch/mipsel/interrupt.rs @@ -155,7 +155,12 @@ fn page_fault(tf: &mut TrapFrame) { }; let tlb_result = root_table.lookup(addr); match tlb_result { - Ok(tlb_entry) => tlb::write_tlb_random(tlb_entry), + Ok(tlb_entry) => { + trace!("PhysAddr = {:x}/{:x}", + tlb_entry.entry_lo0.get_pfn() << 12, + tlb_entry.entry_lo1.get_pfn() << 12); + tlb::write_tlb_random(tlb_entry) + }, Err(()) => { if !crate::memory::handle_page_fault(addr) { crate::trap::error(tf); From 4a812425525b37dc4ff3811b373f98f445225974 Mon Sep 17 00:00:00 2001 From: Yuhao Zhou Date: Mon, 8 Apr 2019 12:50:30 +0800 Subject: [PATCH 74/85] Fix kstack switch. --- kernel/src/arch/mipsel/boot/entry.S | 6 ++++++ kernel/src/arch/mipsel/boot/trap.S | 11 ++++++++--- kernel/src/arch/mipsel/context.rs | 8 ++++++++ kernel/src/arch/mipsel/interrupt.rs | 5 ++++- 4 files changed, 26 insertions(+), 4 deletions(-) diff --git a/kernel/src/arch/mipsel/boot/entry.S b/kernel/src/arch/mipsel/boot/entry.S index 1a2a44b..4bbdc35 100644 --- a/kernel/src/arch/mipsel/boot/entry.S +++ b/kernel/src/arch/mipsel/boot/entry.S @@ -3,12 +3,18 @@ .set noreorder .section .text.entry .globl _start + .extern _root_page_table_buffer + .extern _cur_kstack_ptr _start: # setup stack and gp la sp, bootstacktop la gp, _gp + la t0, _cur_kstack_ptr + la t1, _root_page_table_buffer + sw t1, 0(t0) + # set ebase la t0, trap_entry mfc0 t1, $15 # C0_EBASE diff --git a/kernel/src/arch/mipsel/boot/trap.S b/kernel/src/arch/mipsel/boot/trap.S index d232d33..bd1b02b 100644 --- a/kernel/src/arch/mipsel/boot/trap.S +++ b/kernel/src/arch/mipsel/boot/trap.S @@ -21,8 +21,10 @@ general_trap_vec: trap_from_user: # load kstack, we can use k0 to store something - la k0, kernel_stack - la sp, kernel_stack_top +# la k0, kernel_stack +# la sp, kernel_stack_top + la k0, _cur_kstack_ptr + lw sp, 0(k0) trap_from_kernel: /* @@ -161,7 +163,10 @@ kernel_stack_top: .align 12 #PGSHIFT .global _root_page_table_buffer _root_page_table_buffer: - .space 1024 * 4 # 4KB + .space 1024 * 64 # 64KB .global _root_page_table_ptr _root_page_table_ptr: .space 4 # 4bytes + .global _cur_kstack_ptr +_cur_kstack_ptr: + .space 4 # 4bytes diff --git a/kernel/src/arch/mipsel/context.rs b/kernel/src/arch/mipsel/context.rs index 4dfdad9..70c0458 100644 --- a/kernel/src/arch/mipsel/context.rs +++ b/kernel/src/arch/mipsel/context.rs @@ -149,6 +149,10 @@ pub struct Context { sp: usize, } +extern "C" { + fn _cur_kstack_ptr(); +} + impl Context { /// Switch to another kernel thread. /// @@ -161,6 +165,10 @@ impl Context { fn switch_context(src: *mut Context, dst: *mut Context); } + unsafe { + *(_cur_kstack_ptr as *mut usize) = target.sp; + } + switch_context(self as *mut Context, target as *mut Context); } diff --git a/kernel/src/arch/mipsel/interrupt.rs b/kernel/src/arch/mipsel/interrupt.rs index 5a64411..ffbd5c0 100644 --- a/kernel/src/arch/mipsel/interrupt.rs +++ b/kernel/src/arch/mipsel/interrupt.rs @@ -68,7 +68,10 @@ pub extern fn rust_trap(tf: &mut TrapFrame) { E::TLBModification => page_fault(tf), E::TLBLoadMiss => page_fault(tf), E::TLBStoreMiss => page_fault(tf), - _ => crate::trap::error(tf), + _ => { + error!("Unhandled Exception @ CPU{}: {:?} ", 0, tf.cause.cause()); + crate::trap::error(tf) + } } trace!("Interrupt end"); } From 2baf15acac32d371cf2ff8d9c90dbaf8026d505e Mon Sep 17 00:00:00 2001 From: Yuhao Zhou Date: Mon, 8 Apr 2019 14:29:27 +0800 Subject: [PATCH 75/85] Update kstack switch. --- kernel/src/arch/mipsel/boot/context.S | 7 +++++++ kernel/src/arch/mipsel/boot/trap.S | 7 +++++++ kernel/src/arch/mipsel/context.rs | 8 +------- 3 files changed, 15 insertions(+), 7 deletions(-) diff --git a/kernel/src/arch/mipsel/boot/context.S b/kernel/src/arch/mipsel/boot/context.S index b3c1e72..557776b 100644 --- a/kernel/src/arch/mipsel/boot/context.S +++ b/kernel/src/arch/mipsel/boot/context.S @@ -6,6 +6,7 @@ .section .text.context .globl switch_context .extern _root_page_table_ptr +.extern _cur_kstack_ptr switch_context: // save from's registers @@ -25,6 +26,7 @@ switch_context: // sw ra, 12*4(sp) // sw sp, 13*4(sp) + // save page table address la s0, _root_page_table_ptr lw AT, 0(s0) sw AT, 4(sp) @@ -34,6 +36,11 @@ switch_context: lw AT, 4(sp) sw AT, 0(s0) + // restore kstack ptr + // la s0, _cur_kstack_ptr + // addi s1, sp, 4 * 14 + // sw s1, 0(s0) + lw ra, 0(sp) lw s0, 2*4(sp) lw s1, 3*4(sp) diff --git a/kernel/src/arch/mipsel/boot/trap.S b/kernel/src/arch/mipsel/boot/trap.S index bd1b02b..2d40343 100644 --- a/kernel/src/arch/mipsel/boot/trap.S +++ b/kernel/src/arch/mipsel/boot/trap.S @@ -147,6 +147,13 @@ trap_return: lw fp, 156(sp) lw ra, 160(sp) + // save kernel stack + la k0, _cur_kstack_ptr + addiu k1, sp, 168 + sw k1, 0(k0) + nop + + // restore stack lw sp, 152(sp) eret diff --git a/kernel/src/arch/mipsel/context.rs b/kernel/src/arch/mipsel/context.rs index 70c0458..19b4af1 100644 --- a/kernel/src/arch/mipsel/context.rs +++ b/kernel/src/arch/mipsel/context.rs @@ -149,10 +149,6 @@ pub struct Context { sp: usize, } -extern "C" { - fn _cur_kstack_ptr(); -} - impl Context { /// Switch to another kernel thread. /// @@ -165,9 +161,7 @@ impl Context { fn switch_context(src: *mut Context, dst: *mut Context); } - unsafe { - *(_cur_kstack_ptr as *mut usize) = target.sp; - } + info!("Switch to {:x}", target.sp); switch_context(self as *mut Context, target as *mut Context); } From 39a4dd2ff08f7f16f57b7dae67e26946f890512c Mon Sep 17 00:00:00 2001 From: Harry Chen Date: Mon, 8 Apr 2019 20:53:00 +0800 Subject: [PATCH 76/85] Fix VGA driver, now screen lightens on malta! Signed-off-by: Harry Chen --- kernel/src/arch/mipsel/board/malta/mod.rs | 5 +- kernel/src/arch/mipsel/io.rs | 5 -- kernel/src/arch/mipsel/mod.rs | 8 +-- kernel/src/drivers/bus/mod.rs | 2 +- kernel/src/drivers/bus/pci.rs | 35 +++++++++- kernel/src/drivers/gpu/qemu_stdvga.rs | 82 +++++++++++++++++------ kernel/src/drivers/net/e1000.rs | 4 +- 7 files changed, 105 insertions(+), 36 deletions(-) diff --git a/kernel/src/arch/mipsel/board/malta/mod.rs b/kernel/src/arch/mipsel/board/malta/mod.rs index 2681bd3..9917c70 100644 --- a/kernel/src/arch/mipsel/board/malta/mod.rs +++ b/kernel/src/arch/mipsel/board/malta/mod.rs @@ -1,6 +1,7 @@ use once::*; use alloc::string::String; use mips::registers::cp0; +use crate::drivers::bus::pci; #[path = "../../../../drivers/serial/ti_16c550c.rs"] pub mod serial; @@ -31,7 +32,9 @@ pub fn init_serial_early() { /// Initialize other board drivers pub fn init_driver() { // TODO: add possibly more drivers - vga::init(0xb8000000, 0xb2050000, 800, 600); + vga::init(0xbbe00000, 0xb2050000, 800, 600); + // pci::init(); + fb::init(); } pub fn probe_fb_info(_width: u32, _height: u32, _depth: u32) -> fb::FramebufferResult { diff --git a/kernel/src/arch/mipsel/io.rs b/kernel/src/arch/mipsel/io.rs index 2012a62..e5be3e5 100644 --- a/kernel/src/arch/mipsel/io.rs +++ b/kernel/src/arch/mipsel/io.rs @@ -23,8 +23,3 @@ pub fn putfmt(fmt: Arguments) { console.write_fmt(fmt).unwrap(); } } - -pub fn putchar(c: u8) { - unsafe { SERIAL_PORT.force_unlock() } - SERIAL_PORT.lock().putchar(c); -} diff --git a/kernel/src/arch/mipsel/mod.rs b/kernel/src/arch/mipsel/mod.rs index 9bc4c4e..5976118 100644 --- a/kernel/src/arch/mipsel/mod.rs +++ b/kernel/src/arch/mipsel/mod.rs @@ -51,15 +51,15 @@ pub extern fn rust_main() -> ! { unsafe { memory::clear_bss(); } board::init_serial_early(); - driver::init(); - - println!("Hello MIPS 32 from CPU {}, dtb @ {:#x}", cpu_id, dtb_start); + crate::logging::init(); interrupt::init(); memory::init(); timer::init(); + driver::init(); + + println!("Hello MIPS 32 from CPU {}, dtb @ {:#x}", cpu_id, dtb_start); - crate::logging::init(); crate::drivers::init(dtb_start); crate::process::init(); diff --git a/kernel/src/drivers/bus/mod.rs b/kernel/src/drivers/bus/mod.rs index 673e3ba..cee2283 100644 --- a/kernel/src/drivers/bus/mod.rs +++ b/kernel/src/drivers/bus/mod.rs @@ -1,3 +1,3 @@ -#[cfg(target_arch = "x86_64")] +#[cfg(any(target_arch = "x86_64", target_arch = "mips"))] pub mod pci; pub mod virtio_mmio; diff --git a/kernel/src/drivers/bus/pci.rs b/kernel/src/drivers/bus/pci.rs index 6a143c8..78d0bd6 100644 --- a/kernel/src/drivers/bus/pci.rs +++ b/kernel/src/drivers/bus/pci.rs @@ -10,7 +10,6 @@ use core::cmp::Ordering; use pci::*; use rcore_memory::{paging::PageTable, PAGE_SIZE}; use spin::Mutex; -use x86_64::instructions::port::Port; const PCI_COMMAND: u16 = 0x04; const PCI_CAP_PTR: u16 = 0x34; @@ -26,7 +25,12 @@ const PCI_CAP_ID_MSI: u8 = 0x05; struct PortOpsImpl; +#[cfg(target_arch = "x86_64")] +use x86_64::instructions::port::Port; + +#[cfg(target_arch = "x86_64")] impl PortOps for PortOpsImpl { + unsafe fn read8(&self, port: u16) -> u8 { Port::new(port).read() } @@ -47,6 +51,35 @@ impl PortOps for PortOpsImpl { } } + +#[cfg(target_arch = "mips")] +use crate::util::{read, write}; +#[cfg(feature = "board_malta")] +const PCI_BASE: usize = 0xbbe00000; + +#[cfg(target_arch = "mips")] +impl PortOps for PortOpsImpl { + + unsafe fn read8(&self, port: u16) -> u8 { + read(PCI_BASE + port as usize) + } + unsafe fn read16(&self, port: u16) -> u16 { + read(PCI_BASE + port as usize) + } + unsafe fn read32(&self, port: u16) -> u32 { + read(PCI_BASE + port as usize) + } + unsafe fn write8(&self, port: u16, val: u8) { + write(PCI_BASE + port as usize, val); + } + unsafe fn write16(&self, port: u16, val: u16) { + write(PCI_BASE + port as usize, val); + } + unsafe fn write32(&self, port: u16, val: u32) { + write(PCI_BASE + port as usize, val); + } +} + /// Enable the pci device and its interrupt /// Return assigned MSI interrupt number when applicable unsafe fn enable(loc: Location) -> Option { diff --git a/kernel/src/drivers/gpu/qemu_stdvga.rs b/kernel/src/drivers/gpu/qemu_stdvga.rs index 63a3c21..7467667 100644 --- a/kernel/src/drivers/gpu/qemu_stdvga.rs +++ b/kernel/src/drivers/gpu/qemu_stdvga.rs @@ -2,49 +2,71 @@ use crate::util::{read, write}; -const VGA_MMIO_OFFSET: usize = 0x400 - 0x3c0; +const VGA_MMIO_OFFSET: usize = 0x400 - 0x3C0; const VBE_MMIO_OFFSET: usize = 0x500; -const VGA_AR_ADDR: u16 = 0x3C0; -const VBE_DISPI_INDEX_XRES: u16 = 0x01; -const VBE_DISPI_INDEX_YRES: u16 = 0x02; -const VBE_DISPI_INDEX_BPP: u16 = 0x03; -const VBE_DISPI_INDEX_ENABLE: u16 = 0x04; +const VGA_AR_ADDR : u16 = 0x3C0; +const VBE_DISPI_INDEX_XRES : u16 = 0x1; +const VBE_DISPI_INDEX_YRES : u16 = 0x2; +const VBE_DISPI_INDEX_BPP : u16 = 0x3; +const VBE_DISPI_INDEX_ENABLE : u16 = 0x4; +const VBE_DISPI_INDEX_BANK : u16 = 0x5; +const VBE_DISPI_INDEX_VIRT_WIDTH : u16 = 0x6; +const VBE_DISPI_INDEX_VIRT_HEIGHT : u16 = 0x7; +const VBE_DISPI_INDEX_X_OFFSET : u16 = 0x8; +const VBE_DISPI_INDEX_Y_OFFSET : u16 = 0x9; +const VBE_DISPI_INDEX_VIDEO_MEMORY_64K : u16 = 0xa; -const VGA_AR_PAS: u8 = 0x20; -const VBE_DISPI_ENABLED: u16 = 0x01; +const VGA_AR_PAS : u8 = 0x20; +const VBE_DISPI_ENABLED : u16 = 0x01; +const VBE_DISPI_LFB_ENABLED : u16 = 0x40; + +const PCI_COMMAND: u8 = 0x04; +const PCI_COMMAND_IO: u32 = 0x1; +const PCI_COMMAND_MEMORY: u32 = 0x2; +const PCI_COMMAND_MASTER: u32 = 0x4; +const PCI_COMMAND_SPECIAL: u32 = 0x8; +const PCI_COMMAND_SERR: u32 = 0x100; -const PCIR_COMMAND: u8 = 0x04; -const PCIM_CMD_PORTEN: u32 = 0x0001; -const PCIM_CMD_MEMEN: u32 = 0x0002; fn pci_read_config(pci_base: usize, bus: u8, slot: u8, func: u8, offset: u8) -> u32 { // write config address let address = (1 << 31) | ((bus as u32) << 16) | ((slot as u32) << 11) | ((func as u32) << 8) | (offset as u32); - println!("Address: {:08x}", address); write(pci_base + 0xcf8, address); // do the actual work - read(pci_base + 0xcfc) + let value = read(pci_base + 0xcfc); + debug!("Read {:08x} from PCI address: {:02x}:{:02x}.{:02x} @ 0x{:02x}", value, bus, slot, func, offset); + value } fn pci_write_config(pci_base: usize, bus: u8, slot: u8, func: u8, offset: u8, value: u32) { // write config address let address = (1 << 31) | ((bus as u32) << 16) | ((slot as u32) << 11) | ((func as u32) << 8) | (offset as u32); + debug!("Write {:08x} to PCI address: {:02x}:{:02x}.{:02x} @ 0x{:02x}", value, bus, slot, func, offset); write(pci_base + 0xcf8, address); // do the actual work write(pci_base + 0xcfc, value) } pub fn init(pci_base: usize, vga_base: usize, x_res: u16, y_res: u16) { + + debug!("PCI Controller Base: {:08x}", pci_read_config(pci_base, 0x00, 0x00, 0x00, 0x20)); + + let controller = pci_read_config(pci_base, 0x00, 0x00, 0x00, PCI_COMMAND); + pci_write_config(pci_base, 0x00, 0x00, 0x00, PCI_COMMAND, controller | PCI_COMMAND_MASTER | PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_SERR); - // enable PCI MMIO let pci_vendor = pci_read_config(pci_base, 0x00, 0x12, 0x00, 0x0); - println!("PCI Device ID: {:08x}", pci_vendor); + debug!("VGA PCI Device ID: {:08x}", pci_vendor); - let pci_state = pci_read_config(pci_base, 0x00, 0x12, 0x00, PCIR_COMMAND); - println!("PCI Config Status: {:08x}", pci_state); - pci_write_config(pci_base, 0x00, 0x12, 0x00, PCIR_COMMAND, pci_state | PCIM_CMD_PORTEN | PCIM_CMD_MEMEN); + // enable port and MMIO for vga card + pci_write_config(pci_base, 0x00, 0x12, 0x00, PCI_COMMAND, pci_read_config(pci_base, 0x00, 0x12, 0x00, PCI_COMMAND) | PCI_COMMAND_MEMORY); + // bar 0 + pci_write_config(pci_base, 0x00, 0x12, 0x00, 0x10, 0x10000000); + debug!("VGA PCI BAR 0: {:08x}", pci_read_config(pci_base, 0x00, 0x12, 0x00, 0x10)); + // bar 2 + pci_write_config(pci_base, 0x00, 0x12, 0x00, 0x18, 0x12050000); + debug!("VGA PCI BAR 2: {:08x}", pci_read_config(pci_base, 0x00, 0x12, 0x00, 0x18)); // vga operations @@ -52,6 +74,10 @@ pub fn init(pci_base: usize, vga_base: usize, x_res: u16, y_res: u16) { write(vga_base + VGA_MMIO_OFFSET + (offset as usize), value); }; + let vga_read_io = |offset: u16| -> u8 { + read(vga_base + VGA_MMIO_OFFSET + (offset as usize)) + }; + let vga_write_vbe = |offset: u16, value: u16| { write(vga_base + VBE_MMIO_OFFSET + (offset as usize) * 2, value); }; @@ -60,17 +86,29 @@ pub fn init(pci_base: usize, vga_base: usize, x_res: u16, y_res: u16) { read(vga_base + VBE_MMIO_OFFSET + (offset as usize) * 2) }; - // enable palette access + debug!("VGA Endianess: {:x}", read::(vga_base + 0x604)); + + // unblank vga output + vga_read_io(0x3DA); vga_write_io(VGA_AR_ADDR, VGA_AR_PAS); + debug!("VGA AR: {}", vga_read_io(VGA_AR_ADDR)); + // set resolution and color depth vga_write_vbe(VBE_DISPI_INDEX_XRES, x_res); vga_write_vbe(VBE_DISPI_INDEX_YRES, y_res); + vga_write_vbe(VBE_DISPI_INDEX_VIRT_WIDTH, x_res); + vga_write_vbe(VBE_DISPI_INDEX_VIRT_HEIGHT, y_res); + vga_write_vbe(VBE_DISPI_INDEX_BANK, 0); + vga_write_vbe(VBE_DISPI_INDEX_X_OFFSET, 0); + vga_write_vbe(VBE_DISPI_INDEX_Y_OFFSET, 0); vga_write_vbe(VBE_DISPI_INDEX_BPP, 8); + debug!("VGA Resolution: {}*{}@{}bit", vga_read_vbe(VBE_DISPI_INDEX_XRES), vga_read_vbe(VBE_DISPI_INDEX_YRES), vga_read_vbe(VBE_DISPI_INDEX_BPP)); + // enable vbe let vbe_enable = vga_read_vbe(VBE_DISPI_INDEX_ENABLE); - println!("VBE Status: {:04x}", vbe_enable); - vga_write_vbe(VBE_DISPI_INDEX_ENABLE, vbe_enable | VBE_DISPI_ENABLED); + vga_write_vbe(VBE_DISPI_INDEX_ENABLE, vbe_enable | VBE_DISPI_ENABLED | VBE_DISPI_LFB_ENABLED); + debug!("VBE Status: {:04x}", vga_read_vbe(VBE_DISPI_INDEX_ENABLE)); - println!("QEMU STDVGA driver initialized @ {:x}", vga_base); + info!("QEMU STDVGA driver initialized @ {:x}", vga_base); } diff --git a/kernel/src/drivers/net/e1000.rs b/kernel/src/drivers/net/e1000.rs index fb32d8f..7aa0962 100644 --- a/kernel/src/drivers/net/e1000.rs +++ b/kernel/src/drivers/net/e1000.rs @@ -348,8 +348,8 @@ pub fn e1000_init(name: String, irq: Option, header: usize, size: usize) { let recv_page = unsafe { HEAP_ALLOCATOR.alloc_zeroed(Layout::from_size_align(PAGE_SIZE, PAGE_SIZE).unwrap()) } as usize; - let send_page_pa = active_table().get_entry(send_page).unwrap().target(); - let recv_page_pa = active_table().get_entry(recv_page).unwrap().target(); + let send_page_pa = active_table().get_entry(send_page).unwrap().target() as u64; + let recv_page_pa = active_table().get_entry(recv_page).unwrap().target() as u64; let send_queue_size = PAGE_SIZE / size_of::(); let recv_queue_size = PAGE_SIZE / size_of::(); let mut send_queue = From 9078190e2877fac00f69f3cfc54593750807ca60 Mon Sep 17 00:00:00 2001 From: Yuhao Zhou Date: Mon, 8 Apr 2019 22:35:02 +0800 Subject: [PATCH 77/85] Fix many bugs. * timer counter overflow * clear TLB when switching context * fix cp0.ebase access (sel = 1) * clear TLB when editing page table --- kernel/src/arch/mipsel/boot/context.S | 8 ++++---- kernel/src/arch/mipsel/boot/entry.S | 4 ++-- kernel/src/arch/mipsel/context.rs | 7 +++---- kernel/src/arch/mipsel/paging.rs | 9 ++++++++- kernel/src/arch/mipsel/timer.rs | 5 ++--- 5 files changed, 19 insertions(+), 14 deletions(-) diff --git a/kernel/src/arch/mipsel/boot/context.S b/kernel/src/arch/mipsel/boot/context.S index 557776b..534ede5 100644 --- a/kernel/src/arch/mipsel/boot/context.S +++ b/kernel/src/arch/mipsel/boot/context.S @@ -28,13 +28,13 @@ switch_context: // save page table address la s0, _root_page_table_ptr - lw AT, 0(s0) - sw AT, 4(sp) + lw s1, 0(s0) + sw s1, 4(sp) // restore to's registers lw sp, 0(a1) - lw AT, 4(sp) - sw AT, 0(s0) + lw s1, 4(sp) + sw s1, 0(s0) // restore kstack ptr // la s0, _cur_kstack_ptr diff --git a/kernel/src/arch/mipsel/boot/entry.S b/kernel/src/arch/mipsel/boot/entry.S index 4bbdc35..0e45ba7 100644 --- a/kernel/src/arch/mipsel/boot/entry.S +++ b/kernel/src/arch/mipsel/boot/entry.S @@ -17,9 +17,9 @@ _start: # set ebase la t0, trap_entry - mfc0 t1, $15 # C0_EBASE + mfc0 t1, $15, 1 # C0_EBASE or t1, t1, t0 - mtc0 t1, $15 + mtc0 t1, $15, 1 # exit bootstrap mode mfc0 t0, $12 # C0_STATUS diff --git a/kernel/src/arch/mipsel/context.rs b/kernel/src/arch/mipsel/context.rs index 19b4af1..7e473ad 100644 --- a/kernel/src/arch/mipsel/context.rs +++ b/kernel/src/arch/mipsel/context.rs @@ -118,7 +118,7 @@ impl InitStack { } } -extern { +extern "C" { fn trap_return(); } @@ -161,8 +161,7 @@ impl Context { fn switch_context(src: *mut Context, dst: *mut Context); } - info!("Switch to {:x}", target.sp); - + tlb::clear_all_tlb(); switch_context(self as *mut Context, target as *mut Context); } @@ -230,7 +229,7 @@ impl Context { let mut tf = tf.clone(); tf.sp = ustack_top; // sp tf.v1 = tls; - tf.a0 = 0; // return value + tf.v0 = 0; // return value tf }, }.push_at(kstack_top) diff --git a/kernel/src/arch/mipsel/paging.rs b/kernel/src/arch/mipsel/paging.rs index 47c2899..3771598 100644 --- a/kernel/src/arch/mipsel/paging.rs +++ b/kernel/src/arch/mipsel/paging.rs @@ -51,6 +51,7 @@ extern "C" { pub fn set_root_page_table_ptr(ptr : usize) { unsafe { + clear_all_tlb(); *(_root_page_table_ptr as *mut usize) = ptr; } } @@ -157,13 +158,19 @@ impl InactivePageTable for InactivePageTable0 { self.token() as *mut MIPSPageTable }; + unsafe { clear_all_tlb(); } + let mut active = unsafe { ActivePageTable( TwoLevelPageTable::new(&mut *pt), ::core::mem::uninitialized() ) }; - f(&mut active) + + let ret = f(&mut active); + + unsafe { clear_all_tlb(); } + ret } } diff --git a/kernel/src/arch/mipsel/timer.rs b/kernel/src/arch/mipsel/timer.rs index 9659358..fdc6ecf 100644 --- a/kernel/src/arch/mipsel/timer.rs +++ b/kernel/src/arch/mipsel/timer.rs @@ -19,7 +19,6 @@ pub fn init() { pub fn set_next() { // 100Hz @ QEMU let timebase = 250000; - cp0::compare::write_u32( - cp0::count::read_u32() + timebase - ); + cp0::count::write_u32(0); + cp0::compare::write_u32(timebase); } From 358e682bad73f6e508e1977d4805fea3e30a6e5f Mon Sep 17 00:00:00 2001 From: Harry Chen Date: Tue, 9 Apr 2019 01:08:49 +0800 Subject: [PATCH 78/85] Enable PCI initialization for matal, update mips crate and user app repo Signed-off-by: Harry Chen --- kernel/Cargo.lock | 8 ++++---- kernel/Cargo.toml | 2 +- kernel/src/arch/mipsel/board/malta/mod.rs | 2 +- kernel/src/drivers/gpu/qemu_stdvga.rs | 6 ++++-- user | 2 +- 5 files changed, 11 insertions(+), 9 deletions(-) diff --git a/kernel/Cargo.lock b/kernel/Cargo.lock index c89c9d5..1d95c85 100644 --- a/kernel/Cargo.lock +++ b/kernel/Cargo.lock @@ -229,8 +229,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "mips" -version = "0.1.0" -source = "git+https://github.com/Harry-Chen/rust-mips#7410a6aa107fce681378e7850c03f9b6befec2d2" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bit_field 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", @@ -372,7 +372,7 @@ dependencies = [ "isomorphic_drivers 0.1.0 (git+https://github.com/rcore-os/isomorphic_drivers)", "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "mips 0.1.0 (git+https://github.com/Harry-Chen/rust-mips)", + "mips 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "once 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "paste 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "pc-keyboard 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -688,7 +688,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "e19e8d5c34a3e0e2223db8e060f9e8264aeeb5c5fc64a4ee9965c062211c024b" "checksum log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c84ec4b527950aa83a329754b01dbe3f58361d1c5efacd1f6d68c494d08a17c6" "checksum managed 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "fdcec5e97041c7f0f1c5b7d93f12e57293c831c646f4cc7a5db59460c7ea8de6" -"checksum mips 0.1.0 (git+https://github.com/Harry-Chen/rust-mips)" = "" +"checksum mips 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4cbf449a63e4db77af9f662d6b42068c0925e779a3a7c70ad02f191cf1e6c802" "checksum nodrop 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "2f9667ddcc6cc8a43afc9b7917599d7216aa09c463919ea32c59ed6cac8bc945" "checksum once 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "931fb7a4cf34610cf6cbe58d52a8ca5ef4c726d4e2e178abd0dc13a6551c6d73" "checksum os_bootinfo 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "66481dbeb5e773e7bd85b63cd6042c30786f834338288c5ec4f3742673db360a" diff --git a/kernel/Cargo.toml b/kernel/Cargo.toml index a5c490d..e1d0288 100644 --- a/kernel/Cargo.toml +++ b/kernel/Cargo.toml @@ -78,7 +78,7 @@ aarch64 = { git = "https://github.com/rcore-os/aarch64" } bcm2837 = { git = "https://github.com/rcore-os/bcm2837", optional = true } [target.'cfg(target_arch = "mips")'.dependencies] -mips = { git = "https://github.com/Harry-Chen/rust-mips" } +mips = "^0.2.0" paste = "0.1" [package.metadata.bootimage] diff --git a/kernel/src/arch/mipsel/board/malta/mod.rs b/kernel/src/arch/mipsel/board/malta/mod.rs index 9917c70..b37fa97 100644 --- a/kernel/src/arch/mipsel/board/malta/mod.rs +++ b/kernel/src/arch/mipsel/board/malta/mod.rs @@ -33,7 +33,7 @@ pub fn init_serial_early() { pub fn init_driver() { // TODO: add possibly more drivers vga::init(0xbbe00000, 0xb2050000, 800, 600); - // pci::init(); + pci::init(); fb::init(); } diff --git a/kernel/src/drivers/gpu/qemu_stdvga.rs b/kernel/src/drivers/gpu/qemu_stdvga.rs index 7467667..c6885f0 100644 --- a/kernel/src/drivers/gpu/qemu_stdvga.rs +++ b/kernel/src/drivers/gpu/qemu_stdvga.rs @@ -19,6 +19,7 @@ const VBE_DISPI_INDEX_VIDEO_MEMORY_64K : u16 = 0xa; const VGA_AR_PAS : u8 = 0x20; const VBE_DISPI_ENABLED : u16 = 0x01; +const VBE_DISPI_8BIT_DAC : u16 = 0x20; const VBE_DISPI_LFB_ENABLED : u16 = 0x40; const PCI_COMMAND: u8 = 0x04; @@ -89,10 +90,11 @@ pub fn init(pci_base: usize, vga_base: usize, x_res: u16, y_res: u16) { debug!("VGA Endianess: {:x}", read::(vga_base + 0x604)); // unblank vga output - vga_read_io(0x3DA); vga_write_io(VGA_AR_ADDR, VGA_AR_PAS); debug!("VGA AR: {}", vga_read_io(VGA_AR_ADDR)); + vga_write_vbe(VBE_DISPI_INDEX_ENABLE, 0); + // set resolution and color depth vga_write_vbe(VBE_DISPI_INDEX_XRES, x_res); vga_write_vbe(VBE_DISPI_INDEX_YRES, y_res); @@ -106,7 +108,7 @@ pub fn init(pci_base: usize, vga_base: usize, x_res: u16, y_res: u16) { // enable vbe let vbe_enable = vga_read_vbe(VBE_DISPI_INDEX_ENABLE); - vga_write_vbe(VBE_DISPI_INDEX_ENABLE, vbe_enable | VBE_DISPI_ENABLED | VBE_DISPI_LFB_ENABLED); + vga_write_vbe(VBE_DISPI_INDEX_ENABLE, vbe_enable | VBE_DISPI_ENABLED | VBE_DISPI_LFB_ENABLED | VBE_DISPI_8BIT_DAC); debug!("VBE Status: {:04x}", vga_read_vbe(VBE_DISPI_INDEX_ENABLE)); info!("QEMU STDVGA driver initialized @ {:x}", vga_base); diff --git a/user b/user index 07619a4..2c80f1e 160000 --- a/user +++ b/user @@ -1 +1 @@ -Subproject commit 07619a48d4e8051766c294d9d616337869e4c1a0 +Subproject commit 2c80f1e46fbd6808b80bee9b7fbbb24c11afd29d From 37a69c2a47b868c08c4a33688effd576209f2b96 Mon Sep 17 00:00:00 2001 From: Harry Chen Date: Tue, 9 Apr 2019 12:34:30 +0800 Subject: [PATCH 79/85] Update user repo to latest version, ready for first merge Signed-off-by: Harry Chen --- user | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/user b/user index 2c80f1e..fdaa1be 160000 --- a/user +++ b/user @@ -1 +1 @@ -Subproject commit 2c80f1e46fbd6808b80bee9b7fbbb24c11afd29d +Subproject commit fdaa1be8635944d88ff128da13bf0464f7ce2eb6 From 4fc32572b06afa933eda8cd68089ad3cdcfe82cc Mon Sep 17 00:00:00 2001 From: Harry Chen Date: Tue, 9 Apr 2019 13:31:56 +0800 Subject: [PATCH 80/85] Fix some review problems, add mispel arch to CI Signed-off-by: Harry Chen --- .travis.yml | 10 ++++ kernel/Makefile | 2 +- kernel/src/arch/mipsel/atomic.patch | 72 ----------------------------- kernel/src/arch/mipsel/boot/entry.S | 10 ++-- 4 files changed, 16 insertions(+), 78 deletions(-) delete mode 100644 kernel/src/arch/mipsel/atomic.patch diff --git a/.travis.yml b/.travis.yml index e7ecc38..58f2acf 100644 --- a/.travis.yml +++ b/.travis.yml @@ -28,6 +28,7 @@ env: - ARCH="riscv32" - ARCH="x86_64" - ARCH="aarch64" + - ARCH="mipsel" OPTS="board=malta" matrix: allow_failures: @@ -90,6 +91,15 @@ install: export PATH=$PATH:$PWD/riscv64-linux-musl-cross/bin; fi; fi + - if [ $ARCH = mipsel ]; then + if [ $TRAVIS_OS_NAME = linux ]; then + sudo apt update; + sudo apt install linux-headers-$(uname -r); + wget https://musl.cc/mipsel-linux-musln32-cross.tgz; + tar -xvf mipsel-linux-musln32-cross.tgz; + export PATH=$PATH:$PWD/mipsel-linux-musln32-cross/bin; + fi; + fi before_script: diff --git a/kernel/Makefile b/kernel/Makefile index 2db02a5..d85eed8 100644 --- a/kernel/Makefile +++ b/kernel/Makefile @@ -136,7 +136,7 @@ qemu_opts += \ else ifeq ($(arch), mipsel) ifeq ($(board), malta) qemu_opts += \ - -machine $(board) \ + -machine $(board) -device VGA \ -serial null -serial null -serial mon:stdio \ -kernel $(kernel_img) endif diff --git a/kernel/src/arch/mipsel/atomic.patch b/kernel/src/arch/mipsel/atomic.patch deleted file mode 100644 index d7722b6..0000000 --- a/kernel/src/arch/mipsel/atomic.patch +++ /dev/null @@ -1,72 +0,0 @@ ---- atomic_backup.rs 2018-10-06 19:59:14.000000000 +0800 -+++ atomic.rs 2018-10-26 14:34:31.000000000 +0800 -@@ -125,6 +125,9 @@ - #[cfg(target_has_atomic = "8")] - #[stable(feature = "rust1", since = "1.0.0")] - pub struct AtomicBool { -+ #[cfg(any(target_arch = "riscv32", target_arch = "riscv64"))] -+ v: UnsafeCell, -+ #[cfg(not(any(target_arch = "riscv32", target_arch = "riscv64")))] - v: UnsafeCell, - } - -@@ -265,6 +268,59 @@ - pub const ATOMIC_BOOL_INIT: AtomicBool = AtomicBool::new(false); - - #[cfg(target_has_atomic = "8")] -+#[cfg(any(target_arch = "riscv32", target_arch = "riscv64"))] -+impl AtomicBool { -+ /// -+ #[inline] -+ #[stable(feature = "rust1", since = "1.0.0")] -+ pub const fn new(v: bool) -> AtomicBool { -+ AtomicBool { v: UnsafeCell::new(v as u32) } -+ } -+ -+ /// -+ #[inline] -+ #[stable(feature = "rust1", since = "1.0.0")] -+ pub fn load(&self, order: Ordering) -> bool { -+ unsafe { atomic_load(self.v.get(), order) != 0 } -+ } -+ -+ /// -+ #[inline] -+ #[stable(feature = "rust1", since = "1.0.0")] -+ pub fn store(&self, val: bool, order: Ordering) { -+ unsafe { atomic_store(self.v.get(), val as u32, order); } -+ } -+ -+ /// -+ #[inline] -+ #[stable(feature = "rust1", since = "1.0.0")] -+ pub fn compare_and_swap(&self, current: bool, new: bool, order: Ordering) -> bool { -+ match self.compare_exchange(current, new, order, strongest_failure_ordering(order)) { -+ Ok(x) => x, -+ Err(x) => x, -+ } -+ } -+ -+ /// -+ #[inline] -+ #[stable(feature = "extended_compare_and_swap", since = "1.10.0")] -+ pub fn compare_exchange(&self, -+ current: bool, -+ new: bool, -+ success: Ordering, -+ failure: Ordering) -+ -> Result { -+ match unsafe { -+ atomic_compare_exchange(self.v.get(), current as u32, new as u32, success, failure) -+ } { -+ Ok(x) => Ok(x != 0), -+ Err(x) => Err(x != 0), -+ } -+ } -+} -+ -+#[cfg(target_has_atomic = "8")] -+#[cfg(not(any(target_arch = "riscv32", target_arch = "riscv64")))] - impl AtomicBool { - /// Creates a new `AtomicBool`. - /// diff --git a/kernel/src/arch/mipsel/boot/entry.S b/kernel/src/arch/mipsel/boot/entry.S index 0e45ba7..e72c353 100644 --- a/kernel/src/arch/mipsel/boot/entry.S +++ b/kernel/src/arch/mipsel/boot/entry.S @@ -1,6 +1,6 @@ #include "regdef.h" - .set noreorder + .set noreorder .section .text.entry .globl _start .extern _root_page_table_buffer @@ -8,12 +8,12 @@ _start: # setup stack and gp - la sp, bootstacktop + la sp, bootstacktop la gp, _gp - la t0, _cur_kstack_ptr - la t1, _root_page_table_buffer - sw t1, 0(t0) + la t0, _cur_kstack_ptr + la t1, _root_page_table_buffer + sw t1, 0(t0) # set ebase la t0, trap_entry From aa9bf593e2f82c3777abc82edb83ff05f219361e Mon Sep 17 00:00:00 2001 From: Harry Chen Date: Tue, 9 Apr 2019 13:47:04 +0800 Subject: [PATCH 81/85] Fix Makefile for aarch64, install dtc in travis config Signed-off-by: Harry Chen --- kernel/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/Makefile b/kernel/Makefile index d85eed8..059a716 100644 --- a/kernel/Makefile +++ b/kernel/Makefile @@ -276,7 +276,7 @@ sym: $(bootloader): $(kernel) ifeq ($(arch), aarch64) - need_bootloader := true +need_bootloader := true endif ifeq ($(need_bootloader), true) @echo Building $(arch) bootloader From 782da8761d2987aced8de08afa76cc350d4020a4 Mon Sep 17 00:00:00 2001 From: Harry Chen Date: Tue, 9 Apr 2019 13:51:34 +0800 Subject: [PATCH 82/85] Fix travis config (forget in last commit) Signed-off-by: Harry Chen --- .travis.yml | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/.travis.yml b/.travis.yml index 58f2acf..9e99092 100644 --- a/.travis.yml +++ b/.travis.yml @@ -46,10 +46,10 @@ install: if [ $TRAVIS_OS_NAME = linux ]; then export FILE="gcc-arm-8.2-2018.11-x86_64-aarch64-elf"; wget https://developer.arm.com/-/media/Files/downloads/gnu-a/8.2-2018.11/$FILE.tar.xz; - tar -xvf $FILE.tar.xz; + tar -xf $FILE.tar.xz; export PATH=$PATH:$PWD/$FILE/bin; wget https://musl.cc/aarch64-linux-musl-cross.tgz; - tar -xvf aarch64-linux-musl-cross.tgz; + tar -xf aarch64-linux-musl-cross.tgz; export PATH=$PATH:$PWD/aarch64-linux-musl-cross/bin; elif [ $TRAVIS_OS_NAME = osx ]; then brew tap SergioBenitez/osxct; @@ -61,16 +61,16 @@ install: sudo apt update; sudo apt install linux-headers-$(uname -r); wget https://musl.cc/x86_64-linux-musl-cross.tgz; - tar -xvf x86_64-linux-musl-cross.tgz; + tar -xf x86_64-linux-musl-cross.tgz; export PATH=$PATH:$PWD/x86_64-linux-musl-cross/bin; fi; fi - if [ $TRAVIS_OS_NAME = linux ]; then - wget https://download.qemu.org/qemu-3.1.0.tar.xz && tar xvJf qemu-3.1.0.tar.xz > /dev/null && cd qemu-3.1.0 && ./configure --target-list=$ARCH-softmmu && make && cd ..; + wget https://download.qemu.org/qemu-3.1.0.tar.xz && tar xJf qemu-3.1.0.tar.xz > /dev/null && cd qemu-3.1.0 && ./configure --target-list=$ARCH-softmmu && make && cd ..; export PATH=$PATH:$PWD/qemu-3.1.0/$ARCH-softmmu:$PWD/qemu-3.1.0; sudo apt update; - sudo apt install libfuse-dev; + sudo apt install libfuse-dev device-tree-compiler -y; fi - if [ $ARCH = riscv32 ]; then @@ -78,7 +78,7 @@ install: sudo apt update; sudo apt install linux-headers-$(uname -r); wget https://musl.cc/riscv32-linux-musl-cross.tgz; - tar -xvf riscv32-linux-musl-cross.tgz; + tar -xf riscv32-linux-musl-cross.tgz; export PATH=$PATH:$PWD/riscv32-linux-musl-cross/bin; fi; fi @@ -87,7 +87,7 @@ install: sudo apt update; sudo apt install linux-headers-$(uname -r); wget https://musl.cc/riscv64-linux-musl-cross.tgz; - tar -xvf riscv64-linux-musl-cross.tgz; + tar -xf riscv64-linux-musl-cross.tgz; export PATH=$PATH:$PWD/riscv64-linux-musl-cross/bin; fi; fi @@ -96,7 +96,7 @@ install: sudo apt update; sudo apt install linux-headers-$(uname -r); wget https://musl.cc/mipsel-linux-musln32-cross.tgz; - tar -xvf mipsel-linux-musln32-cross.tgz; + tar -xf mipsel-linux-musln32-cross.tgz; export PATH=$PATH:$PWD/mipsel-linux-musln32-cross/bin; fi; fi From 801b2e609a03669eb130034619169b0afa0176d6 Mon Sep 17 00:00:00 2001 From: Harry Chen Date: Tue, 9 Apr 2019 16:16:09 +0800 Subject: [PATCH 83/85] Fix makefile for aarch64 Signed-off-by: Harry Chen --- kernel/Makefile | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/kernel/Makefile b/kernel/Makefile index 059a716..f44ba3c 100644 --- a/kernel/Makefile +++ b/kernel/Makefile @@ -61,6 +61,7 @@ endif ifeq ($(arch), aarch64) board := raspi3 +need_bootloader := true endif # currently only mipsel architecture needs DTB linked to the kernel @@ -275,9 +276,6 @@ sym: ### bootloader and kernel image ### $(bootloader): $(kernel) -ifeq ($(arch), aarch64) -need_bootloader := true -endif ifeq ($(need_bootloader), true) @echo Building $(arch) bootloader @$(strip) $(kernel) -o $(kernel)_stripped From 9b5f7b8078051f137502dae6c5a538e6faa52753 Mon Sep 17 00:00:00 2001 From: Harry Chen Date: Tue, 9 Apr 2019 17:06:33 +0800 Subject: [PATCH 84/85] Use host gcc for preprocessing in makefile Signed-off-by: Harry Chen --- kernel/Makefile | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/kernel/Makefile b/kernel/Makefile index f44ba3c..78fc4d3 100644 --- a/kernel/Makefile +++ b/kernel/Makefile @@ -219,6 +219,8 @@ strip := $(prefix)strip dtc := dtc export CC = $(cc) +hostcc := gcc + .PHONY: all clean build asm doc debug kernel sfsimg install run justrun runnet justrunnet runui justrunui runtest justruntest all: kernel @@ -333,7 +335,7 @@ else ifeq ($(arch), aarch64) @cargo xbuild $(build_args) else ifeq ($(arch), mipsel) @for file in context entry trap ; do \ - $(cc) -E src/arch/$(arch)/boot/$${file}.S -o src/arch/$(arch)/boot/$${file}.gen.s ; \ + $(hostcc) -E src/arch/$(arch)/boot/$${file}.S -o src/arch/$(arch)/boot/$${file}.gen.s ; \ done @cargo xbuild $(build_args) endif From 75ba0859cff973cf63d38d24e267c03924435c5a Mon Sep 17 00:00:00 2001 From: Harry Chen Date: Tue, 9 Apr 2019 17:08:04 +0800 Subject: [PATCH 85/85] Run cargo fmt Signed-off-by: Harry Chen --- kernel/build.rs | 46 +++---- kernel/src/arch/aarch64/board/raspi3/mod.rs | 8 +- kernel/src/arch/mipsel/board/malta/mod.rs | 16 +-- kernel/src/arch/mipsel/board/mipssim/mod.rs | 12 +- kernel/src/arch/mipsel/board/thinpad/mod.rs | 12 +- kernel/src/arch/mipsel/compiler_rt.rs | 2 +- kernel/src/arch/mipsel/consts.rs | 3 +- kernel/src/arch/mipsel/context.rs | 59 ++++++--- kernel/src/arch/mipsel/cpu.rs | 2 +- kernel/src/arch/mipsel/driver/mod.rs | 2 +- kernel/src/arch/mipsel/interrupt.rs | 44 +++---- kernel/src/arch/mipsel/memory.rs | 15 ++- kernel/src/arch/mipsel/mod.rs | 22 ++-- kernel/src/arch/mipsel/paging.rs | 133 +++++++++++++------- kernel/src/arch/mipsel/rand.rs | 2 +- kernel/src/arch/mipsel/timer.rs | 4 +- kernel/src/backtrace.rs | 20 ++- kernel/src/drivers/bus/pci.rs | 3 - kernel/src/drivers/console/color.rs | 16 ++- kernel/src/drivers/console/mod.rs | 4 +- kernel/src/drivers/gpu/fb.rs | 7 +- kernel/src/drivers/gpu/qemu_stdvga.rs | 117 +++++++++++------ kernel/src/drivers/serial/16550_reg.rs | 51 ++++---- kernel/src/drivers/serial/simple_uart.rs | 11 +- kernel/src/drivers/serial/ti_16c550c.rs | 24 ++-- kernel/src/util/mod.rs | 6 +- 26 files changed, 374 insertions(+), 267 deletions(-) diff --git a/kernel/build.rs b/kernel/build.rs index 6390c32..8e1440f 100644 --- a/kernel/build.rs +++ b/kernel/build.rs @@ -9,23 +9,20 @@ fn main() { println!("cargo:rerun-if-env-changed=BOARD"); println!("cargo:rerun-if-env-changed=SFSIMG"); - let arch: String = std::env::var("ARCH").unwrap(); - let board: String = std::env::var("BOARD").unwrap(); - match arch.as_str() { - "x86_64" => { - gen_vector_asm().unwrap(); - } - "riscv32" => { - } - "riscv64" => { - } - "mipsel" => { - gen_dtb_asm(&arch, &board).unwrap(); - } - "aarch64" => { - } - _ => panic!("Unknown arch {}", arch), - } + let arch: String = std::env::var("ARCH").unwrap(); + let board: String = std::env::var("BOARD").unwrap(); + match arch.as_str() { + "x86_64" => { + gen_vector_asm().unwrap(); + } + "riscv32" => {} + "riscv64" => {} + "mipsel" => { + gen_dtb_asm(&arch, &board).unwrap(); + } + "aarch64" => {} + _ => panic!("Unknown arch {}", arch), + } } fn gen_vector_asm() -> Result<()> { @@ -52,7 +49,6 @@ fn gen_vector_asm() -> Result<()> { Ok(()) } - fn gen_dtb_asm(arch: &String, _board: &String) -> Result<()> { let dtb = std::env::var("DTB").unwrap(); @@ -60,20 +56,24 @@ fn gen_dtb_asm(arch: &String, _board: &String) -> Result<()> { panic!("DTB `{}` not found", dtb) } - let mut f = File::create(format!("src/arch/{}/boot/dtb.gen.s", arch)).unwrap(); + let mut f = File::create(format!("src/arch/{}/boot/dtb.gen.s", arch)).unwrap(); println!("cargo:rerun-if-changed={}", dtb); println!("cargo:rerun-if-env-changed=DTB"); - writeln!(f, "# generated by build.rs - do not edit")?; - write!(f, r#" + writeln!(f, "# generated by build.rs - do not edit")?; + write!( + f, + r#" .section .dtb,"a" .align 12 .global _dtb_start, _dtb_end _dtb_start: .incbin "{}" _dtb_end: - "#, dtb)?; + "#, + dtb + )?; Ok(()) -} \ No newline at end of file +} diff --git a/kernel/src/arch/aarch64/board/raspi3/mod.rs b/kernel/src/arch/aarch64/board/raspi3/mod.rs index dfd7235..1cc6696 100644 --- a/kernel/src/arch/aarch64/board/raspi3/mod.rs +++ b/kernel/src/arch/aarch64/board/raspi3/mod.rs @@ -1,9 +1,8 @@ //! Raspberry PI 3 Model B/B+ +use alloc::string::String; use bcm2837::atags::Atags; use once::*; -use alloc::string::String; - #[path = "../../../../drivers/gpu/fb.rs"] pub mod fb; @@ -48,13 +47,12 @@ pub fn probe_memory() -> Option<(usize, usize)> { } pub fn probe_fb_info(width: u32, height: u32, depth: u32) -> FramebufferResult { - let (width, height) = if width == 0 || height == 0 { mailbox::framebuffer_get_physical_size()? } else { (width, height) }; - + let depth = if depth == 0 { mailbox::framebuffer_get_depth()? } else { @@ -85,4 +83,4 @@ pub fn probe_fb_info(width: u32, height: u32, depth: u32) -> FramebufferResult { } Ok((info, fb::ColorConfig::BGRA8888, vaddr)) -} \ No newline at end of file +} diff --git a/kernel/src/arch/mipsel/board/malta/mod.rs b/kernel/src/arch/mipsel/board/malta/mod.rs index b37fa97..0fbaa33 100644 --- a/kernel/src/arch/mipsel/board/malta/mod.rs +++ b/kernel/src/arch/mipsel/board/malta/mod.rs @@ -1,17 +1,17 @@ -use once::*; +use crate::drivers::bus::pci; use alloc::string::String; use mips::registers::cp0; -use crate::drivers::bus::pci; +use once::*; +#[path = "../../../../drivers/console/mod.rs"] +pub mod console; +pub mod consts; +#[path = "../../../../drivers/gpu/fb.rs"] +pub mod fb; #[path = "../../../../drivers/serial/ti_16c550c.rs"] pub mod serial; #[path = "../../../../drivers/gpu/qemu_stdvga.rs"] pub mod vga; -#[path = "../../../../drivers/gpu/fb.rs"] -pub mod fb; -#[path = "../../../../drivers/console/mod.rs"] -pub mod console; -pub mod consts; use fb::FramebufferInfo; @@ -51,4 +51,4 @@ pub fn probe_fb_info(_width: u32, _height: u32, _depth: u32) -> fb::FramebufferR screen_size: 800 * 600, }; Ok((fb_info, fb::ColorConfig::VgaPalette, 0xb0000000)) -} \ No newline at end of file +} diff --git a/kernel/src/arch/mipsel/board/mipssim/mod.rs b/kernel/src/arch/mipsel/board/mipssim/mod.rs index 4f1a4f4..97eb465 100644 --- a/kernel/src/arch/mipsel/board/mipssim/mod.rs +++ b/kernel/src/arch/mipsel/board/mipssim/mod.rs @@ -1,13 +1,13 @@ -use once::*; use alloc::string::String; +use once::*; -#[path = "../../../../drivers/serial/16550_reg.rs"] -pub mod serial; -#[path = "../../../../drivers/gpu/fb.rs"] -pub mod fb; #[path = "../../../../drivers/console/mod.rs"] pub mod console; pub mod consts; +#[path = "../../../../drivers/gpu/fb.rs"] +pub mod fb; +#[path = "../../../../drivers/serial/16550_reg.rs"] +pub mod serial; /// Initialize serial port first pub fn init_serial_early() { @@ -24,4 +24,4 @@ pub fn init_driver() { pub fn probe_fb_info(_width: u32, _height: u32, _depth: u32) -> fb::FramebufferResult { Err(String::from("Framebuffer not usable on mipssim board")) -} \ No newline at end of file +} diff --git a/kernel/src/arch/mipsel/board/thinpad/mod.rs b/kernel/src/arch/mipsel/board/thinpad/mod.rs index dc4fe8a..dae1f92 100644 --- a/kernel/src/arch/mipsel/board/thinpad/mod.rs +++ b/kernel/src/arch/mipsel/board/thinpad/mod.rs @@ -1,13 +1,13 @@ -use once::*; use alloc::string::String; +use once::*; -#[path = "../../../../drivers/serial/simple_uart.rs"] -pub mod serial; -#[path = "../../../../drivers/gpu/fb.rs"] -pub mod fb; #[path = "../../../../drivers/console/mod.rs"] pub mod console; pub mod consts; +#[path = "../../../../drivers/gpu/fb.rs"] +pub mod fb; +#[path = "../../../../drivers/serial/simple_uart.rs"] +pub mod serial; use fb::FramebufferInfo; use fb::FramebufferResult; @@ -39,4 +39,4 @@ pub fn probe_fb_info(width: u32, height: u32, depth: u32) -> FramebufferResult { screen_size: 800 * 600, }; Ok((fb_info, fb::ColorConfig::RGB332, 0xa2000000)) -} \ No newline at end of file +} diff --git a/kernel/src/arch/mipsel/compiler_rt.rs b/kernel/src/arch/mipsel/compiler_rt.rs index b49a3ce..04ed3c3 100644 --- a/kernel/src/arch/mipsel/compiler_rt.rs +++ b/kernel/src/arch/mipsel/compiler_rt.rs @@ -3,6 +3,6 @@ //! [atomic](http://llvm.org/docs/Atomics.html#libcalls-atomic) #[no_mangle] -pub extern fn abort() { +pub extern "C" fn abort() { panic!("abort"); } diff --git a/kernel/src/arch/mipsel/consts.rs b/kernel/src/arch/mipsel/consts.rs index cf428ee..ff2ef0c 100644 --- a/kernel/src/arch/mipsel/consts.rs +++ b/kernel/src/arch/mipsel/consts.rs @@ -1,6 +1,5 @@ /// Platform specific constants -/// - +/// pub use super::board::consts::*; pub const KERNEL_OFFSET: usize = 0x80100000; diff --git a/kernel/src/arch/mipsel/context.rs b/kernel/src/arch/mipsel/context.rs index 7e473ad..85bc56b 100644 --- a/kernel/src/arch/mipsel/context.rs +++ b/kernel/src/arch/mipsel/context.rs @@ -59,7 +59,7 @@ impl TrapFrame { /// /// The new thread starts at function `entry` with an usize argument `arg`. /// The stack pointer will be set to `sp`. - fn new_kernel_thread(entry: extern fn(usize) -> !, arg: usize, sp: usize) -> Self { + fn new_kernel_thread(entry: extern "C" fn(usize) -> !, arg: usize, sp: usize) -> Self { use core::mem::zeroed; let mut tf: Self = unsafe { zeroed() }; tf.a0 = arg; @@ -89,7 +89,7 @@ impl TrapFrame { } } -use core::fmt::{Debug, Formatter, Error}; +use core::fmt::{Debug, Error, Formatter}; impl Debug for TrapFrame { fn fmt(&self, f: &mut Formatter) -> Result<(), Error> { f.debug_struct("TrapFrame") @@ -136,7 +136,11 @@ struct ContextData { impl ContextData { fn new(satp: usize) -> Self { - ContextData { ra: trap_return as usize, satp, ..ContextData::default() } + ContextData { + ra: trap_return as usize, + satp, + ..ContextData::default() + } } } @@ -175,13 +179,22 @@ impl Context { /// The new thread starts at function `entry` with an usize argument `arg`. /// The stack pointer will be set to `kstack_top`. /// The SATP register will be set to `satp`. - pub unsafe fn new_kernel_thread(entry: extern fn(usize) -> !, arg: usize, kstack_top: usize, satp: usize) -> Self { - info!("New kernel thread @ {:x}, stack = {:x}", entry as usize, kstack_top); + pub unsafe fn new_kernel_thread( + entry: extern "C" fn(usize) -> !, + arg: usize, + kstack_top: usize, + satp: usize, + ) -> Self { + info!( + "New kernel thread @ {:x}, stack = {:x}", + entry as usize, kstack_top + ); InitStack { context: ContextData::new(satp), tf: TrapFrame::new_kernel_thread(entry, arg, kstack_top), - }.push_at(kstack_top) + } + .push_at(kstack_top) } /// Constructs Context for a new user thread. @@ -189,13 +202,23 @@ impl Context { /// The new thread starts at `entry_addr`. /// The stack pointer of user and kernel mode will be set to `ustack_top`, `kstack_top`. /// The SATP register will be set to `satp`. - pub unsafe fn new_user_thread(entry_addr: usize, ustack_top: usize, kstack_top: usize, _is32: bool, satp: usize) -> Self { - info!("New user thread @ {:x}, stack = {:x}", entry_addr, kstack_top); + pub unsafe fn new_user_thread( + entry_addr: usize, + ustack_top: usize, + kstack_top: usize, + _is32: bool, + satp: usize, + ) -> Self { + info!( + "New user thread @ {:x}, stack = {:x}", + entry_addr, kstack_top + ); InitStack { context: ContextData::new(satp), tf: TrapFrame::new_user_thread(entry_addr, ustack_top), - }.push_at(kstack_top) + } + .push_at(kstack_top) } /// Fork a user process and get the new Context. @@ -212,7 +235,8 @@ impl Context { tf.v0 = 0; tf }, - }.push_at(kstack_top) + } + .push_at(kstack_top) } /// Fork a user thread and get the new Context. @@ -222,17 +246,24 @@ impl Context { /// The new user stack will be set to `ustack_top`. /// The new thread pointer will be set to `tls`. /// All the other registers are same as the original. - pub unsafe fn new_clone(tf: &TrapFrame, ustack_top: usize, kstack_top: usize, satp: usize, tls: usize) -> Self { + pub unsafe fn new_clone( + tf: &TrapFrame, + ustack_top: usize, + kstack_top: usize, + satp: usize, + tls: usize, + ) -> Self { InitStack { context: ContextData::new(satp), tf: { let mut tf = tf.clone(); - tf.sp = ustack_top; // sp + tf.sp = ustack_top; // sp tf.v1 = tls; - tf.v0 = 0; // return value + tf.v0 = 0; // return value tf }, - }.push_at(kstack_top) + } + .push_at(kstack_top) } /// Used for getting the init TrapFrame of a new user context in `sys_exec`. diff --git a/kernel/src/arch/mipsel/cpu.rs b/kernel/src/arch/mipsel/cpu.rs index ea27d1f..932744a 100644 --- a/kernel/src/arch/mipsel/cpu.rs +++ b/kernel/src/arch/mipsel/cpu.rs @@ -1,6 +1,6 @@ -use mips::registers::cp0; use crate::consts::MAX_CPU_NUM; use core::ptr::{read_volatile, write_volatile}; +use mips::registers::cp0; static mut STARTED: [bool; MAX_CPU_NUM] = [false; MAX_CPU_NUM]; diff --git a/kernel/src/arch/mipsel/driver/mod.rs b/kernel/src/arch/mipsel/driver/mod.rs index 67c4009..0cf6ad0 100644 --- a/kernel/src/arch/mipsel/driver/mod.rs +++ b/kernel/src/arch/mipsel/driver/mod.rs @@ -3,8 +3,8 @@ use super::board; use once::*; -pub use self::board::serial; pub use self::board::fb; +pub use self::board::serial; #[path = "../../../drivers/console/mod.rs"] pub mod console; diff --git a/kernel/src/arch/mipsel/interrupt.rs b/kernel/src/arch/mipsel/interrupt.rs index ffbd5c0..bc60547 100644 --- a/kernel/src/arch/mipsel/interrupt.rs +++ b/kernel/src/arch/mipsel/interrupt.rs @@ -1,19 +1,21 @@ -use mips::interrupts; -use mips::tlb; -use mips::registers::cp0; -use crate::drivers::DRIVERS; -use mips::paging::{PageTable as MIPSPageTable, PageTableEntry, PageTableFlags as EF, TwoLevelPageTable}; -use mips::addr::*; pub use self::context::*; use crate::arch::paging::get_root_page_table_ptr; +use crate::drivers::DRIVERS; use log::*; +use mips::addr::*; +use mips::interrupts; +use mips::paging::{ + PageTable as MIPSPageTable, PageTableEntry, PageTableFlags as EF, TwoLevelPageTable, +}; +use mips::registers::cp0; +use mips::tlb; #[path = "context.rs"] mod context; /// Initialize interrupt pub fn init() { - extern { + extern "C" { fn trap_entry(); } unsafe { @@ -59,8 +61,8 @@ pub unsafe fn restore(flags: usize) { /// /// This function is called from `trap.asm`. #[no_mangle] -pub extern fn rust_trap(tf: &mut TrapFrame) { - use cp0::cause::{Exception as E}; +pub extern "C" fn rust_trap(tf: &mut TrapFrame) { + use cp0::cause::Exception as E; trace!("Exception @ CPU{}: {:?} ", 0, tf.cause.cause()); match tf.cause.cause() { E::Interrupt => interrupt_dispatcher(tf), @@ -93,7 +95,7 @@ fn external() { let handlers = [try_process_serial, try_process_drivers]; for handler in handlers.iter() { if handler() == true { - break + break; } } } @@ -105,7 +107,7 @@ fn try_process_serial() -> bool { crate::trap::serial(ch); true } - None => false + None => false, } } @@ -113,10 +115,10 @@ fn try_process_drivers() -> bool { // TODO for driver in DRIVERS.read().iter() { if driver.try_handle_interrupt(None) == true { - return true + return true; } } - return false + return false; } fn ipi() { @@ -131,7 +133,7 @@ fn timer() { } fn syscall(tf: &mut TrapFrame) { - tf.epc += 4; // Must before syscall, because of fork. + tf.epc += 4; // Must before syscall, because of fork. let arguments = [tf.a0, tf.a1, tf.a2, tf.a3, tf.t0, tf.t1]; trace!("MIPS syscall {} invoked with {:?}", tf.v0, arguments); @@ -153,17 +155,17 @@ fn page_fault(tf: &mut TrapFrame) { trace!("\nEXCEPTION: Page Fault @ {:#x}", addr); let virt_addr = VirtAddr::new(addr); - let root_table = unsafe { - &mut *(get_root_page_table_ptr() as *mut MIPSPageTable) - }; + let root_table = unsafe { &mut *(get_root_page_table_ptr() as *mut MIPSPageTable) }; let tlb_result = root_table.lookup(addr); match tlb_result { Ok(tlb_entry) => { - trace!("PhysAddr = {:x}/{:x}", - tlb_entry.entry_lo0.get_pfn() << 12, - tlb_entry.entry_lo1.get_pfn() << 12); + trace!( + "PhysAddr = {:x}/{:x}", + tlb_entry.entry_lo0.get_pfn() << 12, + tlb_entry.entry_lo1.get_pfn() << 12 + ); tlb::write_tlb_random(tlb_entry) - }, + } Err(()) => { if !crate::memory::handle_page_fault(addr) { crate::trap::error(tf); diff --git a/kernel/src/arch/mipsel/memory.rs b/kernel/src/arch/mipsel/memory.rs index 67ff901..b54d847 100644 --- a/kernel/src/arch/mipsel/memory.rs +++ b/kernel/src/arch/mipsel/memory.rs @@ -1,9 +1,9 @@ +use crate::arch::paging::*; +use crate::consts::{KERNEL_OFFSET, MEMORY_END, MEMORY_OFFSET}; +use crate::memory::{init_heap, Linear, MemoryAttr, MemorySet, FRAME_ALLOCATOR}; use core::mem; -use rcore_memory::PAGE_SIZE; use log::*; -use crate::memory::{FRAME_ALLOCATOR, init_heap, MemoryAttr, MemorySet, Linear}; -use crate::consts::{MEMORY_OFFSET, MEMORY_END, KERNEL_OFFSET}; -use crate::arch::paging::*; +use rcore_memory::PAGE_SIZE; /// Initialize the memory management module pub fn init() { @@ -29,7 +29,10 @@ fn init_frame_allocator() { use core::ops::Range; let mut ba = FRAME_ALLOCATOR.lock(); - let range = to_range((end as usize) - KERNEL_OFFSET + MEMORY_OFFSET + PAGE_SIZE, MEMORY_END); + let range = to_range( + (end as usize) - KERNEL_OFFSET + MEMORY_OFFSET + PAGE_SIZE, + MEMORY_END, + ); ba.insert(range); info!("frame allocator: init end"); @@ -58,7 +61,7 @@ pub unsafe fn clear_bss() { // Symbols provided by linker script #[allow(dead_code)] -extern { +extern "C" { fn stext(); fn etext(); fn sdata(); diff --git a/kernel/src/arch/mipsel/mod.rs b/kernel/src/arch/mipsel/mod.rs index 5976118..74103db 100644 --- a/kernel/src/arch/mipsel/mod.rs +++ b/kernel/src/arch/mipsel/mod.rs @@ -1,14 +1,14 @@ -pub mod io; -pub mod interrupt; -pub mod timer; -pub mod paging; -pub mod memory; pub mod compiler_rt; pub mod consts; pub mod cpu; -pub mod syscall; -pub mod rand; pub mod driver; +pub mod interrupt; +pub mod io; +pub mod memory; +pub mod paging; +pub mod rand; +pub mod syscall; +pub mod timer; use log::*; use mips::registers::cp0; @@ -25,15 +25,13 @@ pub mod board; #[path = "board/mipssim/mod.rs"] pub mod board; - extern "C" { fn _dtb_start(); fn _dtb_end(); } #[no_mangle] -pub extern fn rust_main() -> ! { - +pub extern "C" fn rust_main() -> ! { // unsafe { cpu::set_cpu_id(hartid); } let ebase = cp0::ebase::read_u32(); @@ -48,7 +46,9 @@ pub extern fn rust_main() -> ! { loop {} } - unsafe { memory::clear_bss(); } + unsafe { + memory::clear_bss(); + } board::init_serial_early(); crate::logging::init(); diff --git a/kernel/src/arch/mipsel/paging.rs b/kernel/src/arch/mipsel/paging.rs index 3771598..a9aa72b 100644 --- a/kernel/src/arch/mipsel/paging.rs +++ b/kernel/src/arch/mipsel/paging.rs @@ -1,11 +1,13 @@ // Depends on kernel use crate::memory::{active_table, alloc_frame, dealloc_frame}; +use log::*; use mips::addr::*; -use mips::tlb::*; -use mips::paging::{Mapper, PageTable as MIPSPageTable, PageTableEntry, PageTableFlags as EF, TwoLevelPageTable}; use mips::paging::{FrameAllocator, FrameDeallocator}; +use mips::paging::{ + Mapper, PageTable as MIPSPageTable, PageTableEntry, PageTableFlags as EF, TwoLevelPageTable, +}; +use mips::tlb::*; use rcore_memory::paging::*; -use log::*; pub struct ActivePageTable(TwoLevelPageTable<'static>, PageEntry); @@ -14,7 +16,6 @@ pub struct ActivePageTable(TwoLevelPageTable<'static>, PageEntry); pub struct PageEntry(&'static mut PageTableEntry, Page); impl PageTable for ActivePageTable { - fn map(&mut self, addr: usize, target: usize) -> &mut Entry { // map the 4K `page` to the 4K `frame` with `flags` let flags = EF::VALID | EF::WRITABLE | EF::CACHEABLE; @@ -22,7 +23,10 @@ impl PageTable for ActivePageTable { let frame = Frame::of_addr(PhysAddr::new(target)); // map the page to the frame using FrameAllocatorForRiscv // we may need frame allocator to alloc frame for new page table(first/second) - self.0.map_to(page, frame, flags, &mut FrameAllocatorForRiscv).unwrap().flush(); + self.0 + .map_to(page, frame, flags, &mut FrameAllocatorForRiscv) + .unwrap() + .flush(); self.get_entry(addr).expect("fail to get entry") } @@ -49,7 +53,7 @@ extern "C" { fn _root_page_table_ptr(); } -pub fn set_root_page_table_ptr(ptr : usize) { +pub fn set_root_page_table_ptr(ptr: usize) { unsafe { clear_all_tlb(); *(_root_page_table_ptr as *mut usize) = ptr; @@ -57,18 +61,13 @@ pub fn set_root_page_table_ptr(ptr : usize) { } pub fn get_root_page_table_ptr() -> usize { - unsafe { - *(_root_page_table_ptr as *mut usize) - } + unsafe { *(_root_page_table_ptr as *mut usize) } } pub fn root_page_table_buffer() -> &'static mut MIPSPageTable { - unsafe { - &mut *(_root_page_table_ptr as *mut MIPSPageTable) - } + unsafe { &mut *(_root_page_table_ptr as *mut MIPSPageTable) } } - impl PageTableExt for ActivePageTable {} /// The virtual address of root page table @@ -77,7 +76,7 @@ impl ActivePageTable { pub unsafe fn new() -> Self { ActivePageTable( TwoLevelPageTable::new(root_page_table_buffer()), - ::core::mem::uninitialized() + ::core::mem::uninitialized(), ) } } @@ -85,34 +84,68 @@ impl ActivePageTable { /// implementation for the Entry trait in /crate/memory/src/paging/mod.rs impl Entry for PageEntry { fn update(&mut self) { - unsafe { clear_all_tlb(); } - } - fn accessed(&self) -> bool { self.0.flags().contains(EF::ACCESSED) } - fn dirty(&self) -> bool { self.0.flags().contains(EF::DIRTY) } - fn writable(&self) -> bool { self.0.flags().contains(EF::WRITABLE) } - fn present(&self) -> bool { self.0.flags().contains(EF::VALID) } - fn clear_accessed(&mut self) { self.0.flags_mut().remove(EF::ACCESSED); } - fn clear_dirty(&mut self) { self.0.flags_mut().remove(EF::DIRTY); } - fn set_writable(&mut self, value: bool) { self.0.flags_mut().set(EF::WRITABLE, value); } - fn set_present(&mut self, value: bool) { self.0.flags_mut().set(EF::VALID, value); } - fn target(&self) -> usize { self.0.addr().as_usize() } + unsafe { + clear_all_tlb(); + } + } + fn accessed(&self) -> bool { + self.0.flags().contains(EF::ACCESSED) + } + fn dirty(&self) -> bool { + self.0.flags().contains(EF::DIRTY) + } + fn writable(&self) -> bool { + self.0.flags().contains(EF::WRITABLE) + } + fn present(&self) -> bool { + self.0.flags().contains(EF::VALID) + } + fn clear_accessed(&mut self) { + self.0.flags_mut().remove(EF::ACCESSED); + } + fn clear_dirty(&mut self) { + self.0.flags_mut().remove(EF::DIRTY); + } + fn set_writable(&mut self, value: bool) { + self.0.flags_mut().set(EF::WRITABLE, value); + } + fn set_present(&mut self, value: bool) { + self.0.flags_mut().set(EF::VALID, value); + } + fn target(&self) -> usize { + self.0.addr().as_usize() + } fn set_target(&mut self, target: usize) { let flags = self.0.flags(); let frame = Frame::of_addr(PhysAddr::new(target)); self.0.set(frame, flags); } - fn writable_shared(&self) -> bool { false } - fn readonly_shared(&self) -> bool { false } - fn set_shared(&mut self, writable: bool) { } - fn clear_shared(&mut self) { } - fn swapped(&self) -> bool { self.0.flags().contains(EF::RESERVED1) } - fn set_swapped(&mut self, value: bool) { self.0.flags_mut().set(EF::RESERVED1, value); } - fn user(&self) -> bool { true } - fn set_user(&mut self, value: bool) { } - fn execute(&self) -> bool { true } - fn set_execute(&mut self, value: bool) { } - fn mmio(&self) -> u8 { 0 } - fn set_mmio(&mut self, _value: u8) { } + fn writable_shared(&self) -> bool { + false + } + fn readonly_shared(&self) -> bool { + false + } + fn set_shared(&mut self, writable: bool) {} + fn clear_shared(&mut self) {} + fn swapped(&self) -> bool { + self.0.flags().contains(EF::RESERVED1) + } + fn set_swapped(&mut self, value: bool) { + self.0.flags_mut().set(EF::RESERVED1, value); + } + fn user(&self) -> bool { + true + } + fn set_user(&mut self, value: bool) {} + fn execute(&self) -> bool { + true + } + fn set_execute(&mut self, value: bool) {} + fn mmio(&self) -> u8 { + 0 + } + fn set_mmio(&mut self, _value: u8) {} } #[derive(Debug)] @@ -127,15 +160,15 @@ impl InactivePageTable for InactivePageTable0 { let target = alloc_frame().expect("failed to allocate frame"); let frame = Frame::of_addr(PhysAddr::new(target)); - let table = unsafe { - &mut *(target as *mut MIPSPageTable) - }; + let table = unsafe { &mut *(target as *mut MIPSPageTable) }; table.zero(); InactivePageTable0 { root_frame: frame } } - fn map_kernel(&mut self) { /* nothing to do */ } + fn map_kernel(&mut self) { + /* nothing to do */ + } fn token(&self) -> usize { self.root_frame.to_kernel_unmapped().as_usize() @@ -150,26 +183,30 @@ impl InactivePageTable for InactivePageTable0 { } fn flush_tlb() { - unsafe { clear_all_tlb(); } + unsafe { + clear_all_tlb(); + } } fn edit(&mut self, f: impl FnOnce(&mut Self::Active) -> T) -> T { - let pt: *mut MIPSPageTable = unsafe { - self.token() as *mut MIPSPageTable - }; + let pt: *mut MIPSPageTable = unsafe { self.token() as *mut MIPSPageTable }; - unsafe { clear_all_tlb(); } + unsafe { + clear_all_tlb(); + } let mut active = unsafe { ActivePageTable( TwoLevelPageTable::new(&mut *pt), - ::core::mem::uninitialized() + ::core::mem::uninitialized(), ) }; let ret = f(&mut active); - unsafe { clear_all_tlb(); } + unsafe { + clear_all_tlb(); + } ret } } diff --git a/kernel/src/arch/mipsel/rand.rs b/kernel/src/arch/mipsel/rand.rs index 7395793..f2f1e2c 100644 --- a/kernel/src/arch/mipsel/rand.rs +++ b/kernel/src/arch/mipsel/rand.rs @@ -1,3 +1,3 @@ pub fn rand() -> u64 { return 0; -} \ No newline at end of file +} diff --git a/kernel/src/arch/mipsel/timer.rs b/kernel/src/arch/mipsel/timer.rs index fdc6ecf..9057c02 100644 --- a/kernel/src/arch/mipsel/timer.rs +++ b/kernel/src/arch/mipsel/timer.rs @@ -1,5 +1,5 @@ -use mips::registers::cp0; use log::*; +use mips::registers::cp0; pub fn read_epoch() -> u64 { // TODO: support RTC @@ -9,7 +9,7 @@ pub fn read_epoch() -> u64 { /// Enable timer interrupt pub fn init() { // Enable supervisor timer interrupt - cp0::status::enable_hard_int5(); // IP(7), timer interrupt + cp0::status::enable_hard_int5(); // IP(7), timer interrupt cp0::count::write_u32(0); set_next(); info!("timer: init end"); diff --git a/kernel/src/backtrace.rs b/kernel/src/backtrace.rs index 4262d53..42d40bf 100644 --- a/kernel/src/backtrace.rs +++ b/kernel/src/backtrace.rs @@ -39,8 +39,7 @@ pub fn lr() -> usize { unsafe { asm!("mov $0, x30" : "=r"(ptr)); } - #[cfg(any(target_arch = "riscv32", - target_arch = "riscv64"))] + #[cfg(any(target_arch = "riscv32", target_arch = "riscv64"))] unsafe { asm!("mv $0, ra" : "=r"(ptr)); } @@ -57,7 +56,6 @@ pub fn lr() -> usize { ptr } - // Print the backtrace starting from the caller pub fn backtrace() { unsafe { @@ -88,7 +86,7 @@ pub fn backtrace() { current_pc - size_of::(), current_fp ); - }, + } _ => { println!( "#{:02} PC: {:#018X} FP: {:#018X}", @@ -125,7 +123,12 @@ pub fn backtrace() { code_ptr = code_ptr.offset(-1); } let sp_offset = (*code_ptr << 16) >> 16; - trace!("Found addiu sp @ {:08X}({:08x}) with sp offset {}", code_ptr as usize, *code_ptr, sp_offset); + trace!( + "Found addiu sp @ {:08X}({:08x}) with sp offset {}", + code_ptr as usize, + *code_ptr, + sp_offset + ); // get the return address offset of last function let mut last_fun_found = false; @@ -139,7 +142,12 @@ pub fn backtrace() { if last_fun_found { // unwind stack let ra_offset = (*code_ptr << 16) >> 16; - trace!("Found sw ra @ {:08X}({:08x}) with ra offset {}", code_ptr as usize, *code_ptr, ra_offset); + trace!( + "Found sw ra @ {:08X}({:08x}) with ra offset {}", + code_ptr as usize, + *code_ptr, + ra_offset + ); current_pc = *(((current_fp as isize) + ra_offset) as *const usize); current_fp = ((current_fp as isize) - sp_offset) as usize; trace!("New PC {:08X} FP {:08X}", current_pc, current_fp); diff --git a/kernel/src/drivers/bus/pci.rs b/kernel/src/drivers/bus/pci.rs index 78d0bd6..9002560 100644 --- a/kernel/src/drivers/bus/pci.rs +++ b/kernel/src/drivers/bus/pci.rs @@ -30,7 +30,6 @@ use x86_64::instructions::port::Port; #[cfg(target_arch = "x86_64")] impl PortOps for PortOpsImpl { - unsafe fn read8(&self, port: u16) -> u8 { Port::new(port).read() } @@ -51,7 +50,6 @@ impl PortOps for PortOpsImpl { } } - #[cfg(target_arch = "mips")] use crate::util::{read, write}; #[cfg(feature = "board_malta")] @@ -59,7 +57,6 @@ const PCI_BASE: usize = 0xbbe00000; #[cfg(target_arch = "mips")] impl PortOps for PortOpsImpl { - unsafe fn read8(&self, port: u16) -> u8 { read(PCI_BASE + port as usize) } diff --git a/kernel/src/drivers/console/color.rs b/kernel/src/drivers/console/color.rs index f3cde77..ed543c1 100644 --- a/kernel/src/drivers/console/color.rs +++ b/kernel/src/drivers/console/color.rs @@ -43,12 +43,20 @@ impl FramebufferColor for RgbColor { #[inline] fn pack32(&self, config: ColorConfig) -> u32 { match config { - ColorConfig::RGB332 => (((self.0 >> 5) << 5) | ((self.1 >> 5) << 2) | (self.2 >> 6)) as u32, - ColorConfig::RGB565 => (((self.0 as u16 & 0xF8) << 8) | ((self.1 as u16 & 0xFC) << 3) | (self.2 as u16 >> 3)) as u32, + ColorConfig::RGB332 => { + (((self.0 >> 5) << 5) | ((self.1 >> 5) << 2) | (self.2 >> 6)) as u32 + } + ColorConfig::RGB565 => { + (((self.0 as u16 & 0xF8) << 8) + | ((self.1 as u16 & 0xFC) << 3) + | (self.2 as u16 >> 3)) as u32 + } // FIXME: qemu and low version RPi use RGBA order for 24/32-bit color depth, // but RPi3 B+ uses BGRA order for 24/32-bit color depth. - ColorConfig::BGRA8888 => ((self.0 as u32) << 16) | ((self.1 as u32) << 8) | (self.2 as u32), - _ => unimplemented!() + ColorConfig::BGRA8888 => { + ((self.0 as u32) << 16) | ((self.1 as u32) << 8) | (self.2 as u32) + } + _ => unimplemented!(), } } } diff --git a/kernel/src/drivers/console/mod.rs b/kernel/src/drivers/console/mod.rs index 71721aa..853cce0 100644 --- a/kernel/src/drivers/console/mod.rs +++ b/kernel/src/drivers/console/mod.rs @@ -10,7 +10,7 @@ use spin::Mutex; use crate::util::escape_parser::{CharacterAttribute, EscapeParser}; -use super::fb::{ColorDepth::*, ColorConfig, FramebufferInfo, FRAME_BUFFER}; +use super::fb::{ColorConfig, ColorDepth::*, FramebufferInfo, FRAME_BUFFER}; use self::color::FramebufferColor; use self::fonts::{Font, Font8x16}; @@ -64,7 +64,7 @@ impl ConsoleBuffer { if let Some(fb) = FRAME_BUFFER.lock().as_mut() { let (mut foreground, mut background) = ( ch.attr.foreground.pack32(fb.color_config), - ch.attr.background.pack32(fb.color_config) + ch.attr.background.pack32(fb.color_config), ); if ch.attr.reverse { core::mem::swap(&mut foreground, &mut background); diff --git a/kernel/src/drivers/gpu/fb.rs b/kernel/src/drivers/gpu/fb.rs index f34473f..54d7e10 100644 --- a/kernel/src/drivers/gpu/fb.rs +++ b/kernel/src/drivers/gpu/fb.rs @@ -152,12 +152,9 @@ impl Framebuffer { color_depth, fb_info: info, }) - }, - Err(e) => { - Err(e)? - }, + } + Err(e) => Err(e)?, } - } #[inline] diff --git a/kernel/src/drivers/gpu/qemu_stdvga.rs b/kernel/src/drivers/gpu/qemu_stdvga.rs index c6885f0..1515f15 100644 --- a/kernel/src/drivers/gpu/qemu_stdvga.rs +++ b/kernel/src/drivers/gpu/qemu_stdvga.rs @@ -5,22 +5,22 @@ use crate::util::{read, write}; const VGA_MMIO_OFFSET: usize = 0x400 - 0x3C0; const VBE_MMIO_OFFSET: usize = 0x500; -const VGA_AR_ADDR : u16 = 0x3C0; -const VBE_DISPI_INDEX_XRES : u16 = 0x1; -const VBE_DISPI_INDEX_YRES : u16 = 0x2; -const VBE_DISPI_INDEX_BPP : u16 = 0x3; -const VBE_DISPI_INDEX_ENABLE : u16 = 0x4; -const VBE_DISPI_INDEX_BANK : u16 = 0x5; -const VBE_DISPI_INDEX_VIRT_WIDTH : u16 = 0x6; -const VBE_DISPI_INDEX_VIRT_HEIGHT : u16 = 0x7; -const VBE_DISPI_INDEX_X_OFFSET : u16 = 0x8; -const VBE_DISPI_INDEX_Y_OFFSET : u16 = 0x9; -const VBE_DISPI_INDEX_VIDEO_MEMORY_64K : u16 = 0xa; - -const VGA_AR_PAS : u8 = 0x20; -const VBE_DISPI_ENABLED : u16 = 0x01; -const VBE_DISPI_8BIT_DAC : u16 = 0x20; -const VBE_DISPI_LFB_ENABLED : u16 = 0x40; +const VGA_AR_ADDR: u16 = 0x3C0; +const VBE_DISPI_INDEX_XRES: u16 = 0x1; +const VBE_DISPI_INDEX_YRES: u16 = 0x2; +const VBE_DISPI_INDEX_BPP: u16 = 0x3; +const VBE_DISPI_INDEX_ENABLE: u16 = 0x4; +const VBE_DISPI_INDEX_BANK: u16 = 0x5; +const VBE_DISPI_INDEX_VIRT_WIDTH: u16 = 0x6; +const VBE_DISPI_INDEX_VIRT_HEIGHT: u16 = 0x7; +const VBE_DISPI_INDEX_X_OFFSET: u16 = 0x8; +const VBE_DISPI_INDEX_Y_OFFSET: u16 = 0x9; +const VBE_DISPI_INDEX_VIDEO_MEMORY_64K: u16 = 0xa; + +const VGA_AR_PAS: u8 = 0x20; +const VBE_DISPI_ENABLED: u16 = 0x01; +const VBE_DISPI_8BIT_DAC: u16 = 0x20; +const VBE_DISPI_LFB_ENABLED: u16 = 0x40; const PCI_COMMAND: u8 = 0x04; const PCI_COMMAND_IO: u32 = 0x1; @@ -29,72 +29,102 @@ const PCI_COMMAND_MASTER: u32 = 0x4; const PCI_COMMAND_SPECIAL: u32 = 0x8; const PCI_COMMAND_SERR: u32 = 0x100; - - fn pci_read_config(pci_base: usize, bus: u8, slot: u8, func: u8, offset: u8) -> u32 { // write config address - let address = (1 << 31) | ((bus as u32) << 16) | ((slot as u32) << 11) | ((func as u32) << 8) | (offset as u32); + let address = (1 << 31) + | ((bus as u32) << 16) + | ((slot as u32) << 11) + | ((func as u32) << 8) + | (offset as u32); write(pci_base + 0xcf8, address); // do the actual work let value = read(pci_base + 0xcfc); - debug!("Read {:08x} from PCI address: {:02x}:{:02x}.{:02x} @ 0x{:02x}", value, bus, slot, func, offset); + debug!( + "Read {:08x} from PCI address: {:02x}:{:02x}.{:02x} @ 0x{:02x}", + value, bus, slot, func, offset + ); value } fn pci_write_config(pci_base: usize, bus: u8, slot: u8, func: u8, offset: u8, value: u32) { // write config address - let address = (1 << 31) | ((bus as u32) << 16) | ((slot as u32) << 11) | ((func as u32) << 8) | (offset as u32); - debug!("Write {:08x} to PCI address: {:02x}:{:02x}.{:02x} @ 0x{:02x}", value, bus, slot, func, offset); + let address = (1 << 31) + | ((bus as u32) << 16) + | ((slot as u32) << 11) + | ((func as u32) << 8) + | (offset as u32); + debug!( + "Write {:08x} to PCI address: {:02x}:{:02x}.{:02x} @ 0x{:02x}", + value, bus, slot, func, offset + ); write(pci_base + 0xcf8, address); // do the actual work write(pci_base + 0xcfc, value) } pub fn init(pci_base: usize, vga_base: usize, x_res: u16, y_res: u16) { - - debug!("PCI Controller Base: {:08x}", pci_read_config(pci_base, 0x00, 0x00, 0x00, 0x20)); + debug!( + "PCI Controller Base: {:08x}", + pci_read_config(pci_base, 0x00, 0x00, 0x00, 0x20) + ); let controller = pci_read_config(pci_base, 0x00, 0x00, 0x00, PCI_COMMAND); - pci_write_config(pci_base, 0x00, 0x00, 0x00, PCI_COMMAND, controller | PCI_COMMAND_MASTER | PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_SERR); + pci_write_config( + pci_base, + 0x00, + 0x00, + 0x00, + PCI_COMMAND, + controller | PCI_COMMAND_MASTER | PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_SERR, + ); let pci_vendor = pci_read_config(pci_base, 0x00, 0x12, 0x00, 0x0); debug!("VGA PCI Device ID: {:08x}", pci_vendor); // enable port and MMIO for vga card - pci_write_config(pci_base, 0x00, 0x12, 0x00, PCI_COMMAND, pci_read_config(pci_base, 0x00, 0x12, 0x00, PCI_COMMAND) | PCI_COMMAND_MEMORY); + pci_write_config( + pci_base, + 0x00, + 0x12, + 0x00, + PCI_COMMAND, + pci_read_config(pci_base, 0x00, 0x12, 0x00, PCI_COMMAND) | PCI_COMMAND_MEMORY, + ); // bar 0 pci_write_config(pci_base, 0x00, 0x12, 0x00, 0x10, 0x10000000); - debug!("VGA PCI BAR 0: {:08x}", pci_read_config(pci_base, 0x00, 0x12, 0x00, 0x10)); + debug!( + "VGA PCI BAR 0: {:08x}", + pci_read_config(pci_base, 0x00, 0x12, 0x00, 0x10) + ); // bar 2 pci_write_config(pci_base, 0x00, 0x12, 0x00, 0x18, 0x12050000); - debug!("VGA PCI BAR 2: {:08x}", pci_read_config(pci_base, 0x00, 0x12, 0x00, 0x18)); - + debug!( + "VGA PCI BAR 2: {:08x}", + pci_read_config(pci_base, 0x00, 0x12, 0x00, 0x18) + ); // vga operations let vga_write_io = |offset: u16, value: u8| { write(vga_base + VGA_MMIO_OFFSET + (offset as usize), value); }; - let vga_read_io = |offset: u16| -> u8 { - read(vga_base + VGA_MMIO_OFFSET + (offset as usize)) - }; + let vga_read_io = |offset: u16| -> u8 { read(vga_base + VGA_MMIO_OFFSET + (offset as usize)) }; let vga_write_vbe = |offset: u16, value: u16| { write(vga_base + VBE_MMIO_OFFSET + (offset as usize) * 2, value); }; - let vga_read_vbe = |offset: u16| -> u16 { - read(vga_base + VBE_MMIO_OFFSET + (offset as usize) * 2) - }; + let vga_read_vbe = + |offset: u16| -> u16 { read(vga_base + VBE_MMIO_OFFSET + (offset as usize) * 2) }; debug!("VGA Endianess: {:x}", read::(vga_base + 0x604)); // unblank vga output vga_write_io(VGA_AR_ADDR, VGA_AR_PAS); debug!("VGA AR: {}", vga_read_io(VGA_AR_ADDR)); - + vga_write_vbe(VBE_DISPI_INDEX_ENABLE, 0); - + // set resolution and color depth vga_write_vbe(VBE_DISPI_INDEX_XRES, x_res); vga_write_vbe(VBE_DISPI_INDEX_YRES, y_res); @@ -104,13 +134,20 @@ pub fn init(pci_base: usize, vga_base: usize, x_res: u16, y_res: u16) { vga_write_vbe(VBE_DISPI_INDEX_X_OFFSET, 0); vga_write_vbe(VBE_DISPI_INDEX_Y_OFFSET, 0); vga_write_vbe(VBE_DISPI_INDEX_BPP, 8); - debug!("VGA Resolution: {}*{}@{}bit", vga_read_vbe(VBE_DISPI_INDEX_XRES), vga_read_vbe(VBE_DISPI_INDEX_YRES), vga_read_vbe(VBE_DISPI_INDEX_BPP)); + debug!( + "VGA Resolution: {}*{}@{}bit", + vga_read_vbe(VBE_DISPI_INDEX_XRES), + vga_read_vbe(VBE_DISPI_INDEX_YRES), + vga_read_vbe(VBE_DISPI_INDEX_BPP) + ); // enable vbe let vbe_enable = vga_read_vbe(VBE_DISPI_INDEX_ENABLE); - vga_write_vbe(VBE_DISPI_INDEX_ENABLE, vbe_enable | VBE_DISPI_ENABLED | VBE_DISPI_LFB_ENABLED | VBE_DISPI_8BIT_DAC); + vga_write_vbe( + VBE_DISPI_INDEX_ENABLE, + vbe_enable | VBE_DISPI_ENABLED | VBE_DISPI_LFB_ENABLED | VBE_DISPI_8BIT_DAC, + ); debug!("VBE Status: {:04x}", vga_read_vbe(VBE_DISPI_INDEX_ENABLE)); info!("QEMU STDVGA driver initialized @ {:x}", vga_base); - } diff --git a/kernel/src/drivers/serial/16550_reg.rs b/kernel/src/drivers/serial/16550_reg.rs index a86e60e..424b839 100644 --- a/kernel/src/drivers/serial/16550_reg.rs +++ b/kernel/src/drivers/serial/16550_reg.rs @@ -2,19 +2,17 @@ #![allow(dead_code)] -use core::fmt::{Write, Result, Arguments}; use crate::util::{read, write}; +use core::fmt::{Arguments, Result, Write}; use spin::Mutex; pub struct SerialPort { - base: usize + base: usize, } impl SerialPort { fn new() -> SerialPort { - SerialPort { - base: 0 - } + SerialPort { base: 0 } } pub fn init(&mut self, base: usize) { @@ -49,7 +47,7 @@ impl SerialPort { } let c = read::(self.base + COM_RX); match c { - 255 => '\0', // null + 255 => '\0', // null c => c as char, } } @@ -65,7 +63,6 @@ impl SerialPort { pub fn putfmt(&mut self, fmt: Arguments) { self.write_fmt(fmt).unwrap(); } - } impl Write for SerialPort { @@ -83,27 +80,25 @@ impl Write for SerialPort { } } - -const COM_RX :usize = 0; // In: Receive buffer (DLAB=0) -const COM_TX :usize = 0; // Out: Transmit buffer (DLAB=0) -const COM_DLL :usize = 0; // Out: Divisor Latch Low (DLAB=1) -const COM_DLM :usize = 1; // Out: Divisor Latch High (DLAB=1) -const COM_IER :usize = 1; // Out: Interrupt Enable Register -const COM_IER_RDI :u8 = 0x01; // Enable receiver data interrupt -const COM_IIR :usize = 2; // In: Interrupt ID Register -const COM_FCR :usize = 2; // Out: FIFO Control Register -const COM_LCR :usize = 3; // Out: Line Control Register -const COM_LCR_DLAB :u8 = 0x80; // Divisor latch access bit -const COM_LCR_WLEN8 :u8 = 0x03; // Wordlength: 8 bits -const COM_MCR :usize = 4; // Out: Modem Control Register -const COM_MCR_RTS :u8 = 0x02; // RTS complement -const COM_MCR_DTR :u8 = 0x01; // DTR complement -const COM_MCR_OUT2 :u8 = 0x08; // Out2 complement -const COM_LSR :usize = 5; // In: Line Status Register -const COM_LSR_DATA :u8 = 0x01; // Data available -const COM_LSR_TXRDY :u8 = 0x20; // Transmit buffer avail -const COM_LSR_TSRE :u8 = 0x40; // Transmitter off - +const COM_RX: usize = 0; // In: Receive buffer (DLAB=0) +const COM_TX: usize = 0; // Out: Transmit buffer (DLAB=0) +const COM_DLL: usize = 0; // Out: Divisor Latch Low (DLAB=1) +const COM_DLM: usize = 1; // Out: Divisor Latch High (DLAB=1) +const COM_IER: usize = 1; // Out: Interrupt Enable Register +const COM_IER_RDI: u8 = 0x01; // Enable receiver data interrupt +const COM_IIR: usize = 2; // In: Interrupt ID Register +const COM_FCR: usize = 2; // Out: FIFO Control Register +const COM_LCR: usize = 3; // Out: Line Control Register +const COM_LCR_DLAB: u8 = 0x80; // Divisor latch access bit +const COM_LCR_WLEN8: u8 = 0x03; // Wordlength: 8 bits +const COM_MCR: usize = 4; // Out: Modem Control Register +const COM_MCR_RTS: u8 = 0x02; // RTS complement +const COM_MCR_DTR: u8 = 0x01; // DTR complement +const COM_MCR_OUT2: u8 = 0x08; // Out2 complement +const COM_LSR: usize = 5; // In: Line Status Register +const COM_LSR_DATA: u8 = 0x01; // Data available +const COM_LSR_TXRDY: u8 = 0x20; // Transmit buffer avail +const COM_LSR_TSRE: u8 = 0x40; // Transmitter off lazy_static! { pub static ref SERIAL_PORT: Mutex = Mutex::new(SerialPort::new()); diff --git a/kernel/src/drivers/serial/simple_uart.rs b/kernel/src/drivers/serial/simple_uart.rs index a23501a..9b34494 100644 --- a/kernel/src/drivers/serial/simple_uart.rs +++ b/kernel/src/drivers/serial/simple_uart.rs @@ -1,11 +1,11 @@ //! naive serial adapter driver for thinpad -use core::fmt::{Write, Result, Arguments}; use crate::util::{read, write}; +use core::fmt::{Arguments, Result, Write}; #[derive(Debug, Clone, Copy)] pub struct SerialPort { - base: usize + base: usize, } const UART_STATUS: usize = 0x0; @@ -15,7 +15,6 @@ const UART_STATUS_CTS: u8 = 0x1; // clear to send signal const UART_STATUS_DR: u8 = 0x2; // data ready signal impl SerialPort { - pub fn init(&mut self, base: usize) { self.base = base; } @@ -34,7 +33,7 @@ impl SerialPort { } let c = read::(self.base + UART_DATA); match c { - 255 => '\0', // null + 255 => '\0', // null c => c as char, } } @@ -73,9 +72,7 @@ impl Write for SerialPort { } } -pub static SERIAL_PORT: SerialPort = SerialPort { - base: 0 -}; +pub static SERIAL_PORT: SerialPort = SerialPort { base: 0 }; pub fn init(base: usize) { SERIAL_PORT.lock().init(base); diff --git a/kernel/src/drivers/serial/ti_16c550c.rs b/kernel/src/drivers/serial/ti_16c550c.rs index 79a47d9..4f5b51a 100644 --- a/kernel/src/drivers/serial/ti_16c550c.rs +++ b/kernel/src/drivers/serial/ti_16c550c.rs @@ -2,19 +2,17 @@ #![allow(dead_code)] -use core::fmt::{Write, Result, Arguments}; -use spin::Mutex; use crate::util::{read, write}; +use core::fmt::{Arguments, Result, Write}; +use spin::Mutex; pub struct SerialPort { - base: usize + base: usize, } impl SerialPort { fn new() -> SerialPort { - SerialPort { - base: 0 - } + SerialPort { base: 0 } } pub fn init(&mut self, base: usize) { @@ -49,7 +47,7 @@ impl SerialPort { } let c = read::(self.base + COM_RX); match c { - 255 => '\0', // null + 255 => '\0', // null c => c as char, } } @@ -65,7 +63,6 @@ impl SerialPort { pub fn putfmt(&mut self, fmt: Arguments) { self.write_fmt(fmt).unwrap(); } - } impl Write for SerialPort { @@ -83,12 +80,11 @@ impl Write for SerialPort { } } -const COM_RX :usize = 0x00; // In: Receive buffer (DLAB=0) -const COM_TX :usize = 0x00; // Out: Transmit buffer (DLAB=0) -const COM_INT_EN :usize = 0x08; // In: Interrupt enable -const COM_INT_ID :usize = 0x10; // Out: Interrupt identification -const COM_LSR :usize = 0x28; // In: Line status register - +const COM_RX: usize = 0x00; // In: Receive buffer (DLAB=0) +const COM_TX: usize = 0x00; // Out: Transmit buffer (DLAB=0) +const COM_INT_EN: usize = 0x08; // In: Interrupt enable +const COM_INT_ID: usize = 0x10; // Out: Interrupt identification +const COM_LSR: usize = 0x28; // In: Line status register lazy_static! { pub static ref SERIAL_PORT: Mutex = Mutex::new(SerialPort::new()); diff --git a/kernel/src/util/mod.rs b/kernel/src/util/mod.rs index 0b41620..d0d1f8a 100644 --- a/kernel/src/util/mod.rs +++ b/kernel/src/util/mod.rs @@ -19,11 +19,13 @@ pub unsafe fn write_cstr(ptr: *mut u8, s: &str) { #[inline(always)] pub fn write(addr: usize, content: T) { let cell = (addr) as *mut T; - unsafe { write_volatile(cell, content); } + unsafe { + write_volatile(cell, content); + } } #[inline(always)] pub fn read(addr: usize) -> T { let cell = (addr) as *const T; unsafe { read_volatile(cell) } -} \ No newline at end of file +}