mirror of
https://github.com/rcore-os/rCore.git
synced 2024-11-22 08:06:17 +04:00
impl M-mode kernel for riscv32
This commit is contained in:
parent
2f8cfabbca
commit
fcf5074500
@ -6,14 +6,6 @@ pub unsafe fn disable_and_store() -> usize {
|
||||
rflags & (1 << 9)
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
#[cfg(target_arch = "riscv32")]
|
||||
pub unsafe fn disable_and_store() -> usize {
|
||||
let sstatus: usize;
|
||||
asm!("csrrci $0, 0x100, 2" : "=r"(sstatus));
|
||||
sstatus & 2
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
pub unsafe fn restore(flags: usize) {
|
||||
@ -22,10 +14,28 @@ pub unsafe fn restore(flags: usize) {
|
||||
}
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
#[cfg(target_arch = "riscv32")]
|
||||
pub unsafe fn disable_and_store() -> usize {
|
||||
if option_env!("m_mode").is_some() {
|
||||
let mstatus: usize;
|
||||
asm!("csrrci $0, 0x300, 1 << 3" : "=r"(mstatus));
|
||||
mstatus & (1 << 3)
|
||||
} else {
|
||||
let sstatus: usize;
|
||||
asm!("csrrci $0, 0x100, 1 << 1" : "=r"(sstatus));
|
||||
sstatus & (1 << 1)
|
||||
}
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
#[cfg(target_arch = "riscv32")]
|
||||
pub unsafe fn restore(flags: usize) {
|
||||
asm!("csrs 0x100, $0" :: "r"(flags));
|
||||
if option_env!("m_mode").is_some() {
|
||||
asm!("csrs 0x300, $0" :: "r"(flags));
|
||||
} else {
|
||||
asm!("csrs 0x100, $0" :: "r"(flags));
|
||||
}
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
|
2
kernel/Cargo.lock
generated
2
kernel/Cargo.lock
generated
@ -218,7 +218,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "riscv"
|
||||
version = "0.3.0"
|
||||
source = "git+https://github.com/riscv-and-rust-and-decaf/riscv#f358204af01f2374ab6ed6ea059f724cd5f2fe6f"
|
||||
source = "git+https://github.com/riscv-and-rust-and-decaf/riscv#966eb26d5e8d77677f645d5e32877c678dcee572"
|
||||
dependencies = [
|
||||
"bare-metal 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"bit_field 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -5,8 +5,13 @@ authors = ["Runji Wang <wangrunji0408@163.com>"]
|
||||
edition = "2018"
|
||||
|
||||
[features]
|
||||
# Without BBL (for riscv32 FPGA board)
|
||||
no_bbl = []
|
||||
# Disable paging (for riscv32)
|
||||
no_mmu = []
|
||||
# Kernel in M-mode (for riscv32)
|
||||
m_mode = ["no_mmu"]
|
||||
# (for aarch64 RaspberryPi3)
|
||||
board_raspi3 = []
|
||||
|
||||
[profile.dev]
|
||||
|
@ -15,14 +15,16 @@
|
||||
# smp = 1 | 2 | ... SMP core number
|
||||
# board = fpga Only available on riscv32, build without bbl, run on board
|
||||
# | raspi3 Only available on aarch64, run on Raspberry Pi 3 Model B/B+
|
||||
# nommu Only available on riscv32, build for M-Mode, without MMU
|
||||
# m_mode Only available on riscv32, build for M-Mode, without MMU
|
||||
|
||||
arch ?= riscv32
|
||||
board ?= raspi3
|
||||
mode ?= debug
|
||||
LOG ?= debug
|
||||
smp ?= 4
|
||||
nommu ?=
|
||||
# NOTE: crate 'process' use this name 'm_mode' as an environment
|
||||
# to set interrupt (MIE or SIE)
|
||||
m_mode ?=
|
||||
|
||||
target := $(arch)-blog_os
|
||||
kernel := target/$(target)/$(mode)/ucore
|
||||
@ -45,7 +47,7 @@ else ifeq ($(arch), riscv32)
|
||||
qemu_opts += \
|
||||
-machine virt \
|
||||
-kernel $(bin)
|
||||
ifdef nommu
|
||||
ifdef m_mode
|
||||
qemu_opts += -cpu rv32imacu-nommu
|
||||
endif
|
||||
|
||||
@ -67,8 +69,8 @@ features += no_bbl
|
||||
endif
|
||||
endif
|
||||
|
||||
ifdef nommu
|
||||
features += no_mmu
|
||||
ifdef m_mode
|
||||
features += no_mmu m_mode
|
||||
bbl_m_mode := --enable-boot-machine
|
||||
endif
|
||||
|
||||
|
@ -1,11 +1,19 @@
|
||||
# Constants / Macros defined in Rust code:
|
||||
# xscratch
|
||||
# xstatus
|
||||
# xepc
|
||||
# xcause
|
||||
# xtval
|
||||
# XRET
|
||||
|
||||
.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, 0x140, sp # sscratch
|
||||
csrrw sp, (xscratch), sp
|
||||
bnez sp, _save_context
|
||||
_restore_kernel_sp:
|
||||
csrr sp, 0x140 # sscratch
|
||||
csrr sp, (xscratch)
|
||||
# sscratch = previous-sp, sp = kernel-sp
|
||||
_save_context:
|
||||
# provide room for trap frame
|
||||
@ -45,11 +53,11 @@ _save_context:
|
||||
|
||||
# get sp, sstatus, sepc, stval, scause
|
||||
# set sscratch = 0
|
||||
csrrw s0, 0x140, x0 # sscratch
|
||||
csrr s1, 0x100 # sstatus
|
||||
csrr s2, 0x141 # sepc
|
||||
csrr s3, 0x143 # stval
|
||||
csrr s4, 0x142 # scause
|
||||
csrrw s0, (xscratch), x0
|
||||
csrr s1, (xstatus)
|
||||
csrr s2, (xepc)
|
||||
csrr s3, (xtval)
|
||||
csrr s4, (xcause)
|
||||
# store sp, sstatus, sepc, sbadvaddr, scause
|
||||
sw s0, 2*4(sp)
|
||||
sw s1, 32*4(sp)
|
||||
@ -65,11 +73,11 @@ _save_context:
|
||||
bnez s0, _restore_context # back to S-mode? (sstatus.SPP = 1)
|
||||
_save_kernel_sp:
|
||||
addi s0, sp, 36*4
|
||||
csrw 0x140, s0 # sscratch = kernel-sp
|
||||
csrw (xscratch), s0 # sscratch = kernel-sp
|
||||
_restore_context:
|
||||
# restore sstatus, sepc
|
||||
csrw 0x100, s1
|
||||
csrw 0x141, s2
|
||||
csrw (xstatus), s1
|
||||
csrw (xepc), s2
|
||||
|
||||
# restore x registers except x2 (sp)
|
||||
lw x1, 1*4(sp)
|
||||
@ -116,4 +124,4 @@ __alltraps:
|
||||
__trapret:
|
||||
RESTORE_ALL
|
||||
# return from supervisor call
|
||||
sret
|
||||
XRET
|
||||
|
@ -1,13 +1,24 @@
|
||||
use riscv::register::*;
|
||||
#[cfg(feature = "m_mode")]
|
||||
use riscv::register::{
|
||||
mstatus as xstatus,
|
||||
mstatus::Mstatus as Xstatus,
|
||||
mcause::Mcause,
|
||||
};
|
||||
#[cfg(not(feature = "m_mode"))]
|
||||
use riscv::register::{
|
||||
sstatus as xstatus,
|
||||
sstatus::Sstatus as Xstatus,
|
||||
mcause::Mcause,
|
||||
};
|
||||
|
||||
#[derive(Clone)]
|
||||
#[repr(C)]
|
||||
pub struct TrapFrame {
|
||||
pub x: [usize; 32], // general registers
|
||||
pub sstatus: sstatus::Sstatus, // Supervisor Status Register
|
||||
pub sstatus: Xstatus, // Supervisor Status Register
|
||||
pub sepc: usize, // Supervisor exception program counter, save the trap virtual address (here is used to save the process program entry addr?)
|
||||
pub sbadaddr: usize, // Supervisor bad address
|
||||
pub scause: scause::Scause, // scause register: record the cause of exception/interrupt/trap
|
||||
pub stval: usize, // Supervisor trap value
|
||||
pub scause: Mcause, // scause register: record the cause of exception/interrupt/trap
|
||||
}
|
||||
|
||||
/// Generate the trapframe for building new thread in kernel
|
||||
@ -28,13 +39,13 @@ impl TrapFrame {
|
||||
tf.x[10] = arg; // a0
|
||||
tf.x[2] = sp;
|
||||
tf.sepc = entry as usize;
|
||||
tf.sstatus = sstatus::read();
|
||||
// Supervisor Previous Interrupt Enable
|
||||
tf.sstatus.set_spie(true);
|
||||
// Supervisor Interrupt Disable
|
||||
tf.sstatus.set_sie(false);
|
||||
// Supervisor Previous Privilege Mode is Supervisor
|
||||
tf.sstatus.set_spp(sstatus::SPP::Supervisor);
|
||||
tf.sstatus = xstatus::read();
|
||||
tf.sstatus.set_xpie(true);
|
||||
tf.sstatus.set_xie(false);
|
||||
#[cfg(feature = "m_mode")]
|
||||
tf.sstatus.set_mpp(xstatus::MPP::Machine);
|
||||
#[cfg(not(feature = "m_mode"))]
|
||||
tf.sstatus.set_spp(xstatus::SPP::Supervisor);
|
||||
tf
|
||||
}
|
||||
|
||||
@ -52,10 +63,13 @@ impl TrapFrame {
|
||||
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.sstatus = xstatus::read();
|
||||
tf.sstatus.set_xpie(true);
|
||||
tf.sstatus.set_xie(false);
|
||||
#[cfg(feature = "m_mode")]
|
||||
tf.sstatus.set_mpp(xstatus::MPP::User);
|
||||
#[cfg(not(feature = "m_mode"))]
|
||||
tf.sstatus.set_spp(xstatus::SPP::User);
|
||||
tf
|
||||
}
|
||||
}
|
||||
@ -78,7 +92,7 @@ impl Debug for TrapFrame {
|
||||
.field("regs", &Regs(&self.x))
|
||||
.field("sstatus", &self.sstatus)
|
||||
.field("sepc", &self.sepc)
|
||||
.field("sbadaddr", &self.sbadaddr)
|
||||
.field("stval", &self.stval)
|
||||
.field("scause", &self.scause)
|
||||
.finish()
|
||||
}
|
||||
|
@ -1,4 +1,16 @@
|
||||
use riscv::register::*;
|
||||
#[cfg(feature = "m_mode")]
|
||||
use riscv::register::{
|
||||
mstatus as xstatus,
|
||||
mscratch as xscratch,
|
||||
mtvec as xtvec,
|
||||
};
|
||||
#[cfg(not(feature = "m_mode"))]
|
||||
use riscv::register::{
|
||||
sstatus as xstatus,
|
||||
sscratch as xscratch,
|
||||
stvec as xtvec,
|
||||
};
|
||||
use riscv::register::{mcause, mepc, sie};
|
||||
pub use self::context::*;
|
||||
use crate::memory::{MemorySet, InactivePageTable0};
|
||||
use log::*;
|
||||
@ -17,13 +29,16 @@ pub fn init() {
|
||||
unsafe {
|
||||
// Set sscratch register to 0, indicating to exception vector that we are
|
||||
// presently executing in the kernel
|
||||
sscratch::write(0);
|
||||
xscratch::write(0);
|
||||
// Set the exception vector address
|
||||
stvec::write(__alltraps as usize, stvec::TrapMode::Direct);
|
||||
xtvec::write(__alltraps as usize, xtvec::TrapMode::Direct);
|
||||
// Enable IPI
|
||||
sie::set_ssoft();
|
||||
// Enable serial interrupt
|
||||
sie::set_sext();
|
||||
// NOTE: In M-mode: mie.MSIE is set by BBL.
|
||||
// mie.MEIE can not be set in QEMU v3.0
|
||||
// (seems like a bug)
|
||||
}
|
||||
info!("interrupt: init end");
|
||||
}
|
||||
@ -34,7 +49,7 @@ pub fn init() {
|
||||
*/
|
||||
#[inline(always)]
|
||||
pub unsafe fn enable() {
|
||||
sstatus::set_sie();
|
||||
xstatus::set_xie();
|
||||
}
|
||||
|
||||
/*
|
||||
@ -45,8 +60,8 @@ pub unsafe fn enable() {
|
||||
*/
|
||||
#[inline(always)]
|
||||
pub unsafe fn disable_and_store() -> usize {
|
||||
let e = sstatus::read().sie() as usize;
|
||||
sstatus::clear_sie();
|
||||
let e = xstatus::read().xie() as usize;
|
||||
xstatus::clear_xie();
|
||||
e
|
||||
}
|
||||
|
||||
@ -59,7 +74,7 @@ pub unsafe fn disable_and_store() -> usize {
|
||||
#[inline(always)]
|
||||
pub unsafe fn restore(flags: usize) {
|
||||
if flags != 0 {
|
||||
sstatus::set_sie();
|
||||
xstatus::set_xie();
|
||||
}
|
||||
}
|
||||
|
||||
@ -71,9 +86,15 @@ pub unsafe fn restore(flags: usize) {
|
||||
*/
|
||||
#[no_mangle]
|
||||
pub extern fn rust_trap(tf: &mut TrapFrame) {
|
||||
use riscv::register::scause::{Trap, Interrupt as I, Exception as E};
|
||||
use self::mcause::{Trap, Interrupt as I, Exception as E};
|
||||
trace!("Interrupt @ CPU{}: {:?} ", super::cpu::id(), tf.scause.cause());
|
||||
match tf.scause.cause() {
|
||||
// M-mode only
|
||||
Trap::Interrupt(I::MachineExternal) => serial(),
|
||||
Trap::Interrupt(I::MachineSoft) => ipi(),
|
||||
Trap::Interrupt(I::MachineTimer) => timer(),
|
||||
Trap::Exception(E::MachineEnvCall) => sbi(tf),
|
||||
|
||||
Trap::Interrupt(I::SupervisorExternal) => serial(),
|
||||
Trap::Interrupt(I::SupervisorSoft) => ipi(),
|
||||
Trap::Interrupt(I::SupervisorTimer) => timer(),
|
||||
@ -87,6 +108,12 @@ pub extern fn rust_trap(tf: &mut TrapFrame) {
|
||||
trace!("Interrupt end");
|
||||
}
|
||||
|
||||
/// Call BBL SBI functions for M-mode kernel
|
||||
fn sbi(tf: &mut TrapFrame) {
|
||||
(super::BBL.mcall_trap)(tf.x.as_ptr(), tf.scause.bits(), tf.sepc);
|
||||
tf.sepc += 4;
|
||||
}
|
||||
|
||||
fn serial() {
|
||||
crate::trap::serial(super::io::getchar());
|
||||
}
|
||||
@ -101,8 +128,8 @@ fn ipi() {
|
||||
* process timer interrupt
|
||||
*/
|
||||
fn timer() {
|
||||
crate::trap::timer();
|
||||
super::timer::set_next();
|
||||
crate::trap::timer();
|
||||
}
|
||||
|
||||
/*
|
||||
@ -124,9 +151,8 @@ fn syscall(tf: &mut TrapFrame) {
|
||||
* process IllegalInstruction exception
|
||||
*/
|
||||
fn illegal_inst(tf: &mut TrapFrame) {
|
||||
if !emulate_mul_div(tf) {
|
||||
crate::trap::error(tf);
|
||||
}
|
||||
(super::BBL.illegal_insn_trap)(tf.x.as_ptr(), tf.scause.bits(), tf.sepc);
|
||||
tf.sepc = mepc::read();
|
||||
}
|
||||
|
||||
/*
|
||||
@ -136,73 +162,10 @@ fn illegal_inst(tf: &mut TrapFrame) {
|
||||
* process page fault exception
|
||||
*/
|
||||
fn page_fault(tf: &mut TrapFrame) {
|
||||
let addr = stval::read();
|
||||
let addr = tf.stval;
|
||||
trace!("\nEXCEPTION: Page Fault @ {:#x}", addr);
|
||||
|
||||
if !crate::memory::page_fault_handler(addr) {
|
||||
crate::trap::error(tf);
|
||||
}
|
||||
}
|
||||
|
||||
/// Migrate from riscv-pk
|
||||
/*
|
||||
* @param:
|
||||
* TrapFrame: the Trapframe for the illegal inst exception
|
||||
* @brief:
|
||||
* emulate the multiply and divide operation (if not this kind of operation return false)
|
||||
* @retval:
|
||||
* a bool indicates whether emulate the multiply and divide operation successfully
|
||||
*/
|
||||
fn emulate_mul_div(tf: &mut TrapFrame) -> bool {
|
||||
let insn = unsafe { *(tf.sepc as *const usize) };
|
||||
let rs1 = tf.x[get_reg(insn, RS1)];
|
||||
let rs2 = tf.x[get_reg(insn, RS2)];
|
||||
|
||||
let rd = if (insn & MASK_MUL) == MATCH_MUL {
|
||||
rs1 * rs2
|
||||
} else if (insn & MASK_DIV) == MATCH_DIV {
|
||||
((rs1 as i32) / (rs2 as i32)) as usize
|
||||
} else if (insn & MASK_DIVU) == MATCH_DIVU {
|
||||
rs1 / rs2
|
||||
} else if (insn & MASK_REM) == MATCH_REM {
|
||||
((rs1 as i32) % (rs2 as i32)) as usize
|
||||
} else if (insn & MASK_REMU) == MATCH_REMU {
|
||||
rs1 % rs2
|
||||
} else if (insn & MASK_MULH) == MATCH_MULH {
|
||||
(((rs1 as i32 as i64) * (rs2 as i32 as i64)) >> 32) as usize
|
||||
} else if (insn & MASK_MULHU) == MATCH_MULHU {
|
||||
(((rs1 as i64) * (rs2 as i64)) >> 32) as usize
|
||||
} else if (insn & MASK_MULHSU) == MATCH_MULHSU {
|
||||
(((rs1 as i32 as i64) * (rs2 as i64)) >> 32) as usize
|
||||
} else {
|
||||
return false;
|
||||
};
|
||||
tf.x[get_reg(insn, RD)] = rd;
|
||||
tf.sepc += 4; // jump to next instruction
|
||||
return true;
|
||||
|
||||
fn get_reg(inst: usize, offset: usize) -> usize {
|
||||
(inst >> offset) & 0x1f
|
||||
}
|
||||
|
||||
const RS1: usize = 15;
|
||||
const RS2: usize = 20;
|
||||
const RD: usize = 7;
|
||||
|
||||
const MATCH_MUL: usize = 0x2000033;
|
||||
const MASK_MUL: usize = 0xfe00707f;
|
||||
const MATCH_MULH: usize = 0x2001033;
|
||||
const MASK_MULH: usize = 0xfe00707f;
|
||||
const MATCH_MULHSU: usize = 0x2002033;
|
||||
const MASK_MULHSU: usize = 0xfe00707f;
|
||||
const MATCH_MULHU: usize = 0x2003033;
|
||||
const MASK_MULHU: usize = 0xfe00707f;
|
||||
const MATCH_DIV: usize = 0x2004033;
|
||||
const MASK_DIV: usize = 0xfe00707f;
|
||||
const MATCH_DIVU: usize = 0x2005033;
|
||||
const MASK_DIVU: usize = 0xfe00707f;
|
||||
const MATCH_REM: usize = 0x2006033;
|
||||
const MASK_REM: usize = 0xfe00707f;
|
||||
const MATCH_REMU: usize = 0x2007033;
|
||||
const MASK_REMU: usize = 0xfe00707f;
|
||||
}
|
@ -20,23 +20,29 @@ impl Write for SerialPort {
|
||||
}
|
||||
|
||||
fn putchar(c: u8) {
|
||||
#[cfg(feature = "no_bbl")]
|
||||
unsafe {
|
||||
while read_volatile(STATUS) & CAN_WRITE == 0 {}
|
||||
write_volatile(DATA, c as u8);
|
||||
if cfg!(feature = "no_bbl") {
|
||||
unsafe {
|
||||
while read_volatile(STATUS) & CAN_WRITE == 0 {}
|
||||
write_volatile(DATA, c as u8);
|
||||
}
|
||||
} else if cfg!(feature = "m_mode") {
|
||||
(super::BBL.mcall_console_putchar)(c);
|
||||
} else {
|
||||
sbi::console_putchar(c as usize);
|
||||
}
|
||||
#[cfg(not(feature = "no_bbl"))]
|
||||
sbi::console_putchar(c as usize);
|
||||
}
|
||||
|
||||
pub fn getchar() -> char {
|
||||
#[cfg(feature = "no_bbl")]
|
||||
let c = unsafe {
|
||||
while read_volatile(STATUS) & CAN_READ == 0 {}
|
||||
read_volatile(DATA)
|
||||
let c = if cfg!(feature = "no_bbl") {
|
||||
unsafe {
|
||||
// while read_volatile(STATUS) & CAN_READ == 0 {}
|
||||
read_volatile(DATA)
|
||||
}
|
||||
} else if cfg!(feature = "m_mode") {
|
||||
(super::BBL.mcall_console_getchar)() as u8
|
||||
} else {
|
||||
sbi::console_getchar() as u8
|
||||
};
|
||||
#[cfg(not(feature = "no_bbl"))]
|
||||
let c = sbi::console_getchar() as u8;
|
||||
|
||||
match c {
|
||||
255 => '\0', // null
|
||||
|
@ -8,9 +8,10 @@ pub mod consts;
|
||||
pub mod cpu;
|
||||
|
||||
#[no_mangle]
|
||||
pub extern fn rust_main(hartid: usize, dtb: usize, hart_mask: usize) -> ! {
|
||||
pub extern fn rust_main(hartid: usize, dtb: usize, hart_mask: usize, functions: usize) -> ! {
|
||||
unsafe { cpu::set_cpu_id(hartid); }
|
||||
println!("Hello RISCV! in hart {}, {}, {}", hartid, dtb, hart_mask);
|
||||
unsafe { BBL_FUNCTIONS_PTR = functions as *const _; }
|
||||
println!("Hello RISCV! in hart {}, dtb @ {:#x}, functions @ {:#x}", hartid, dtb, functions);
|
||||
|
||||
if hartid != 0 {
|
||||
while unsafe { !cpu::has_started(hartid) } { }
|
||||
@ -35,7 +36,46 @@ fn others_main() -> ! {
|
||||
crate::kmain();
|
||||
}
|
||||
|
||||
|
||||
/// Constant & Macro for `trap.asm`
|
||||
#[cfg(feature = "m_mode")]
|
||||
global_asm!("
|
||||
.equ xstatus, 0x300
|
||||
.equ xscratch, 0x340
|
||||
.equ xepc, 0x341
|
||||
.equ xcause, 0x342
|
||||
.equ xtval, 0x343
|
||||
.macro XRET\n mret\n .endm
|
||||
");
|
||||
#[cfg(not(feature = "m_mode"))]
|
||||
global_asm!("
|
||||
.equ xstatus, 0x100
|
||||
.equ xscratch, 0x140
|
||||
.equ xepc, 0x141
|
||||
.equ xcause, 0x142
|
||||
.equ xtval, 0x143
|
||||
.macro XRET\n sret\n .endm
|
||||
");
|
||||
|
||||
#[cfg(feature = "no_bbl")]
|
||||
global_asm!(include_str!("boot/boot.asm"));
|
||||
global_asm!(include_str!("boot/entry.asm"));
|
||||
global_asm!(include_str!("boot/trap.asm"));
|
||||
global_asm!(include_str!("boot/trap.asm"));
|
||||
|
||||
|
||||
/// Some symbols passed from BBL.
|
||||
/// Used in M-mode kernel.
|
||||
#[repr(C)]
|
||||
struct BBLFunctions {
|
||||
mcall_trap: BBLTrapHandler,
|
||||
illegal_insn_trap: BBLTrapHandler,
|
||||
mcall_console_putchar: extern fn(u8),
|
||||
mcall_console_getchar: extern fn() -> usize,
|
||||
}
|
||||
|
||||
type BBLTrapHandler = extern fn(regs: *const usize, mcause: usize, mepc: usize);
|
||||
static mut BBL_FUNCTIONS_PTR: *const BBLFunctions = ::core::ptr::null();
|
||||
use lazy_static::lazy_static;
|
||||
lazy_static! {
|
||||
static ref BBL: BBLFunctions = unsafe { BBL_FUNCTIONS_PTR.read() };
|
||||
}
|
@ -33,6 +33,9 @@ pub fn get_cycle() -> u64 {
|
||||
*/
|
||||
pub fn init() {
|
||||
// Enable supervisor timer interrupt
|
||||
#[cfg(feature = "m_mode")]
|
||||
unsafe { mie::set_mtimer(); }
|
||||
#[cfg(not(feature = "m_mode"))]
|
||||
unsafe { sie::set_stimer(); }
|
||||
|
||||
set_next();
|
||||
|
@ -88,6 +88,14 @@ impl Stdin {
|
||||
self.pushed.notify_one();
|
||||
}
|
||||
pub fn pop(&self) -> char {
|
||||
// QEMU v3.0 don't support M-mode external interrupt (bug?)
|
||||
// So we have to use polling.
|
||||
#[cfg(feature = "m_mode")]
|
||||
loop {
|
||||
let c = crate::arch::io::getchar();
|
||||
if c != '\0' { return c; }
|
||||
}
|
||||
#[cfg(not(feature = "m_mode"))]
|
||||
loop {
|
||||
let ret = self.buf.lock().pop_front();
|
||||
match ret {
|
||||
|
2
riscv-pk
2
riscv-pk
@ -1 +1 @@
|
||||
Subproject commit 98d2ffbb3203e1d9a936b067c51f8522a5ff9677
|
||||
Subproject commit 71b2addd7ada2f07ca8e6f02787d706afa4fbe66
|
Loading…
Reference in New Issue
Block a user