Merge branch 'mipsel' of github.com:oscourse-tsinghua/rcore_plus into mipsel

master
Yuhao Zhou 6 years ago
commit d46c10a0a2

@ -28,6 +28,7 @@ env:
- ARCH="riscv32"
- ARCH="x86_64"
- ARCH="aarch64"
- ARCH="mipsel" OPTS="board=malta"
matrix:
allow_failures:
@ -45,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;
@ -60,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
@ -77,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
@ -86,10 +87,19 @@ 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
- 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 -xf mipsel-linux-musln32-cross.tgz;
export PATH=$PATH:$PWD/mipsel-linux-musln32-cross/bin;
fi;
fi
before_script:

8
kernel/Cargo.lock generated

@ -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)" = "<none>"
"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"

@ -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]

@ -61,6 +61,7 @@ endif
ifeq ($(arch), aarch64)
board := raspi3
need_bootloader := true
endif
# currently only mipsel architecture needs DTB linked to the kernel
@ -136,7 +137,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
@ -218,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
@ -275,9 +278,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
@ -335,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

@ -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(())
}
}

@ -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))
}
}

@ -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<u32>,
+ #[cfg(not(any(target_arch = "riscv32", target_arch = "riscv64")))]
v: UnsafeCell<u8>,
}
@@ -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<bool, bool> {
+ 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`.
///

@ -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;
@ -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();
}
@ -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))
}
}

@ -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"))
}
}

@ -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))
}
}

@ -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

@ -1,6 +1,5 @@
/// Platform specific constants
///
///
pub use super::board::consts::*;
pub const KERNEL_OFFSET: usize = 0x80100000;

@ -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`.

@ -2,6 +2,7 @@ use mips::registers::cp0;
use mips::instructions;
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];

@ -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;

@ -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);

@ -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();

@ -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();

@ -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<T>(&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
}
}

@ -1,3 +1,3 @@
pub fn rand() -> u64 {
return 0;
}
}

@ -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");

@ -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::<usize>(),
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);

@ -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)
}

@ -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!(),
}
}
}

@ -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<F: Font> ConsoleBuffer<F> {
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);

@ -152,12 +152,9 @@ impl Framebuffer {
color_depth,
fb_info: info,
})
},
Err(e) => {
Err(e)?
},
}
Err(e) => Err(e)?,
}
}
#[inline]

@ -5,21 +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_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;
@ -28,71 +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::<u32>(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);
@ -102,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);
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);
}

@ -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::<u8>(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<SerialPort> = Mutex::new(SerialPort::new());

@ -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::<u8>(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);

@ -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::<u8>(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<SerialPort> = Mutex::new(SerialPort::new());

@ -19,11 +19,13 @@ pub unsafe fn write_cstr(ptr: *mut u8, s: &str) {
#[inline(always)]
pub fn write<T>(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<T>(addr: usize) -> T {
let cell = (addr) as *const T;
unsafe { read_volatile(cell) }
}
}

@ -1 +1 @@
Subproject commit 07619a48d4e8051766c294d9d616337869e4c1a0
Subproject commit fdaa1be8635944d88ff128da13bf0464f7ce2eb6
Loading…
Cancel
Save