remove remaining M-Mode & K210 code. improve docs in context.rs

master
WangRunji 6 years ago
parent ff82679ddc
commit 01a0f961e9

@ -1,38 +0,0 @@
.section .text.boot
boot:
csrwi mie, 0
csrwi mip, 0
csrwi mscratch, 0
csrwi medeleg, 0
csrwi mideleg, 0
// enable float unit
li t0, 0x00006000 // MSTATUS_FS
csrw mstatus, t0
// uart init
lui x1, 0x38000
li t0, 3384
sw t0, 0x18(x1)
li t0, 1
sw t0, 0x8(x1)
sw t0, 0xc(x1)
li t0, 3
sw t0, 0x14(x1)
sw x0, 0x10(x1)
1: // test
lw t0, 0(x1)
blt t0, zero, 1b
// write
li t0, 0x21
sw t0, 0(x1)
csrr a0, mhartid
// FIXME: enable core 1
li a2, 0 // hart_mask
j _start

@ -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 = 0x40000000;
SECTIONS
{
/* Load the kernel at this address: "." means the current address */
. = BASE_ADDRESS;
start = .;
.text : {
stext = .;
KEEP(*(.text.boot))
*(.text .text.*)
. = ALIGN(4K);
etext = .;
}
.rodata : {
srodata = .;
*(.rodata .rodata.*)
. = ALIGN(4K);
erodata = .;
}
.data : {
sdata = .;
*(.data .data.*)
edata = .;
}
.stack : {
*(.bss.stack)
}
.bss : {
sbss = .;
*(.bss .bss.* .sbss.*)
ebss = .;
}
PROVIDE(end = .);
}

@ -1,10 +1,4 @@
# Constants / Macros defined in Rust code:
# xscratch
# xstatus
# xepc
# xcause
# xtval
# XRET
# XLENB
# LOAD
# STORE
@ -14,10 +8,10 @@
# 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, (xscratch), sp
csrrw sp, sscratch, sp
bnez sp, trap_from_user
trap_from_kernel:
csrr sp, (xscratch)
csrr sp, sscratch
STORE gp, -1
# sscratch = previous-sp, sp = kernel-sp
trap_from_user:
@ -60,11 +54,11 @@ trap_from_user:
# get sp, sstatus, sepc, stval, scause
# set sscratch = 0
csrrw s0, (xscratch), x0
csrr s1, (xstatus)
csrr s2, (xepc)
csrr s3, (xtval)
csrr s4, (xcause)
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
@ -76,16 +70,16 @@ trap_from_user:
.macro RESTORE_ALL
LOAD s1, 32 # s1 = sstatus
LOAD s2, 33 # s2 = sepc
TEST_BACK_TO_KERNEL
andi s0, s1, 1 << 8 # sstatus.SPP = 1
bnez s0, _to_kernel # s0 = back to kernel?
_to_user:
addi s0, sp, 37*XLENB
csrw (xscratch), s0 # sscratch = kernel-sp
csrw sscratch, s0 # sscratch = kernel-sp
STORE gp, 36 # store hartid from gp to sp[36]
_to_kernel:
# restore sstatus, sepc
csrw (xstatus), s1
csrw (xepc), s2
csrw sstatus, s1
csrw sepc, s2
# restore x registers except x2 (sp)
LOAD x1, 1
@ -132,4 +126,4 @@ trap_entry:
trap_return:
RESTORE_ALL
# return from supervisor call
XRET
sret

@ -1,67 +1,58 @@
use riscv::register::{
sstatus as xstatus,
sstatus::Sstatus as Xstatus,
mcause::Mcause,
sstatus,
sstatus::Sstatus,
scause::Scause,
};
/// Saved registers on a trap.
#[derive(Clone)]
#[repr(C)]
pub struct TrapFrame {
pub x: [usize; 32], // general registers
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 stval: usize, // Supervisor trap value
pub scause: Mcause, // scause register: record the cause of exception/interrupt/trap
pub _hartid: usize, // reserve space
/// 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,
}
/// Generate the trapframe for building new thread in kernel
impl TrapFrame {
/*
* @param:
* entry: program entry for the thread
* arg: a0
* sp: stack top
* @brief:
* generate a trapfram for building a new kernel thread
* @retval:
* the trapframe for new kernel thread
*/
/// 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 = xstatus::read();
{
tf.sstatus.set_spie(true);
tf.sstatus.set_sie(false);
tf.sstatus.set_spp(xstatus::SPP::Supervisor);
}
tf.sstatus = sstatus::read();
tf.sstatus.set_spie(true);
tf.sstatus.set_sie(false);
tf.sstatus.set_spp(sstatus::SPP::Supervisor);
tf
}
/*
* @param:
* entry_addr: program entry for the thread
* sp: stack top
* @brief:
* generate a trapfram for building a new user thread
* @retval:
* the trapframe for new user thread
*/
/// 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 = xstatus::read();
{
tf.sstatus.set_spie(true);
tf.sstatus.set_sie(false);
tf.sstatus.set_spp(xstatus::SPP::User);
}
tf.sstatus = sstatus::read();
tf.sstatus.set_spie(true);
tf.sstatus.set_sie(false);
tf.sstatus.set_spp(sstatus::SPP::User);
tf
}
}
@ -85,12 +76,12 @@ impl Debug for TrapFrame {
.field("sstatus", &self.sstatus)
.field("sepc", &self.sepc)
.field("stval", &self.stval)
.field("scause", &self.scause)
.field("scause", &self.scause.cause())
.finish()
}
}
/// kernel stack contents for a new thread
/// Kernel stack contents for a new thread
#[derive(Debug)]
#[repr(C)]
pub struct InitStack {
@ -99,18 +90,11 @@ pub struct InitStack {
}
impl InitStack {
/*
* @param:
* stack_top: the pointer to kernel stack stop
* @brief:
* save the InitStack on the kernel stack stop
* @retval:
* a Context with ptr in it
*/
/// 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).offset(-1); //real kernel stack top
let ptr = (stack_top as *mut Self).sub(1); //real kernel stack top
*ptr = self;
Context(ptr as usize)
Context { sp: ptr as usize }
}
}
@ -118,24 +102,32 @@ 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 {
// satp(asid) just like cr3, save the physical address for Page directory?
ContextData { ra: trap_return as usize, satp, ..ContextData::default() }
}
}
/// A struct only contain one usize element
/// Context of a kernel thread.
#[derive(Debug)]
pub struct Context(usize);
#[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.
@ -208,66 +200,43 @@ impl Context {
: : : : "volatile" )
}
/*
* @brief:
* generate a null Context
* @retval:
* a null Context
*/
/// Constructs a null Context for the current running thread.
pub unsafe fn null() -> Self {
Context(0)
Context { sp: 0 }
}
/*
* @param:
* entry: program entry for the thread
* arg: a0
* kstack_top: kernel stack top
* cr3: cr3 register, save the physical address of Page directory
* @brief:
* generate the content of kernel stack for the new kernel thread and save it's address at kernel stack top - 1
* @retval:
* a Context struct with the pointer to the kernel stack top - 1 as its only element
*/
pub unsafe fn new_kernel_thread(entry: extern fn(usize) -> !, arg: usize, kstack_top: usize, cr3: usize) -> Self {
/// 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(cr3),
context: ContextData::new(satp),
tf: TrapFrame::new_kernel_thread(entry, arg, kstack_top),
}.push_at(kstack_top)
}
/*
* @param:
* entry_addr: program entry for the thread
* ustack_top: user stack top
* kstack_top: kernel stack top
* is32: whether the cpu is 32 bit or not
* cr3: cr3 register, save the physical address of Page directory
* @brief:
* generate the content of kernel stack for the new user thread and save it's address at kernel stack top - 1
* @retval:
* a Context struct with the pointer to the kernel stack top - 1 as its only element
*/
pub unsafe fn new_user_thread(entry_addr: usize, ustack_top: usize, kstack_top: usize, _is32: bool, cr3: usize) -> Self {
/// 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(cr3),
context: ContextData::new(satp),
tf: TrapFrame::new_user_thread(entry_addr, ustack_top),
}.push_at(kstack_top)
}
/*
* @param:
* TrapFrame: the trapframe of the forked process(thread)
* kstack_top: kernel stack top
* cr3: cr3 register, save the physical address of Page directory
* @brief:
* fork and generate a new process(thread) Context according to the TrapFrame and save it's address at kernel stack top - 1
* @retval:
* a Context struct with the pointer to the kernel stack top - 1 as its only element
*/
pub unsafe fn new_fork(tf: &TrapFrame, kstack_top: usize, cr3: usize) -> Self {
/// 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(cr3),
context: ContextData::new(satp),
tf: {
let mut tf = tf.clone();
// fork function's ret value, the new process is 0
@ -277,9 +246,16 @@ impl Context {
}.push_at(kstack_top)
}
pub unsafe fn new_clone(tf: &TrapFrame, ustack_top: usize, kstack_top: usize, cr3: usize, tls: usize) -> Self {
/// 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(cr3),
context: ContextData::new(satp),
tf: {
let mut tf = tf.clone();
tf.x[2] = ustack_top; // sp
@ -290,9 +266,8 @@ impl Context {
}.push_at(kstack_top)
}
/// Called at a new user context
/// To get the init TrapFrame in sys_exec
/// Used for getting the init TrapFrame of a new user context in `sys_exec`.
pub unsafe fn get_init_tf(&self) -> TrapFrame {
(*(self.0 as *const InitStack)).tf.clone()
(*(self.sp as *const InitStack)).tf.clone()
}
}

@ -1,9 +1,4 @@
use riscv::register::{
sstatus as xstatus,
sscratch as xscratch,
stvec as xtvec,
};
use riscv::register::{mcause, mepc, sie, mie};
use riscv::register::*;
use crate::drivers::DRIVERS;
pub use self::context::*;
use log::*;
@ -22,17 +17,14 @@ pub fn init() {
unsafe {
// Set sscratch register to 0, indicating to exception vector that we are
// presently executing in the kernel
xscratch::write(0);
sscratch::write(0);
// Set the exception vector address
xtvec::write(trap_entry as usize, xtvec::TrapMode::Direct);
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();
// 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");
@ -44,13 +36,13 @@ pub fn init() {
*/
#[inline]
pub unsafe fn enable() {
xstatus::set_sie();
sstatus::set_sie();
}
#[inline]
pub unsafe fn disable_and_store() -> usize {
let e = xstatus::read().sie() as usize;
xstatus::clear_sie();
let e = sstatus::read().sie() as usize;
sstatus::clear_sie();
e
}
@ -75,19 +67,12 @@ pub unsafe fn restore(flags: usize) {
*/
#[no_mangle]
pub extern fn rust_trap(tf: &mut TrapFrame) {
use self::mcause::{Trap, Interrupt as I, Exception as E};
use self::scause::{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) => external(),
Trap::Interrupt(I::MachineSoft) => ipi(),
Trap::Interrupt(I::MachineTimer) => timer(),
Trap::Exception(E::MachineEnvCall) => sbi(tf),
Trap::Interrupt(I::SupervisorExternal) => external(),
Trap::Interrupt(I::SupervisorSoft) => ipi(),
Trap::Interrupt(I::SupervisorTimer) => timer(),
Trap::Exception(E::IllegalInstruction) => illegal_inst(tf),
Trap::Exception(E::UserEnvCall) => syscall(tf),
Trap::Exception(E::LoadPageFault) => page_fault(tf),
Trap::Exception(E::StorePageFault) => page_fault(tf),
@ -97,12 +82,6 @@ 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 external() {
#[cfg(feature = "board_u540")]
unsafe { super::board::handle_external_interrupt(); }
@ -161,17 +140,6 @@ fn syscall(tf: &mut TrapFrame) {
tf.x[10] = ret as usize;
}
/*
* @param:
* TrapFrame: the Trapframe for the illegal inst exception
* @brief:
* process IllegalInstruction exception
*/
fn illegal_inst(tf: &mut TrapFrame) {
(super::BBL.illegal_insn_trap)(tf.x.as_ptr(), tf.scause.bits(), tf.sepc);
tf.sepc = mepc::read();
}
/*
* @param:
* TrapFrame: the Trapframe for the page fault exception

@ -16,22 +16,21 @@ mod sbi;
use log::*;
#[no_mangle]
pub extern fn rust_main(hartid: usize, dtb: usize, hart_mask: usize, functions: usize) -> ! {
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}, functions @ {:#x}", hartid, dtb, functions);
println!("Hello RISCV! in hart {}, dtb @ {:#x}", hartid, dtb);
others_main();
//other_main -> !
}
unsafe { memory::clear_bss(); }
unsafe { BBL_FUNCTIONS_PTR = functions as *const _; }
println!("Hello RISCV! in hart {}, dtb @ {:#x}, functions @ {:#x}", hartid, dtb, functions);
println!("Hello RISCV! in hart {}, dtb @ {:#x}", hartid, dtb);
crate::logging::init();
interrupt::init();
@ -61,18 +60,6 @@ const BOOT_HART_ID: usize = 0;
const BOOT_HART_ID: usize = 1;
/// Constant & Macro for `trap.asm`
global_asm!("
.equ xstatus, 0x100
.equ xscratch, 0x140
.equ xepc, 0x141
.equ xcause, 0x142
.equ xtval, 0x143
.macro XRET\n sret\n .endm
.macro TEST_BACK_TO_KERNEL
andi s0, s1, 1 << 8 // sstatus.SPP = 1
.endm
");
#[cfg(target_arch = "riscv32")]
global_asm!(r"
.equ XLENB, 4
@ -99,21 +86,3 @@ global_asm!(r"
global_asm!(include_str!("boot/entry.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() };
}

Loading…
Cancel
Save