1
0
mirror of https://github.com/sgmarz/osblog.git synced 2024-11-24 02:16:19 +04:00

Added comments

This commit is contained in:
Stephen Marz 2019-11-10 09:20:40 -05:00
parent e2dfa8661f
commit b3cd92dc41
3 changed files with 52 additions and 14 deletions

View File

@ -6,6 +6,10 @@
use core::ptr::null_mut;
/// In 64-bit mode, we're given three different modes for the MMU:
/// 0 - The MMU is off -- no protection and no translation PA = VA
/// 8 - This is Sv39 mode -- 39-bit virtual addresses
/// 9 - This is Sv48 mode -- 48-bit virtual addresses
#[repr(usize)]
pub enum SatpMode {
Off = 0,
@ -13,6 +17,10 @@ pub enum SatpMode {
Sv48 = 9,
}
/// The trap frame is set into a structure
/// and packed into each hart's mscratch register.
/// This allows for quick reference and full
/// context switch handling.
#[repr(C)]
#[derive(Clone, Copy)]
pub struct TrapFrame {
@ -23,6 +31,14 @@ pub struct TrapFrame {
pub hartid: usize, // 528
}
/// Rust requires that we initialize our structures
/// because of the move semantics. What'll happen below
/// is Rust will construct a new TrapFrame and move it
/// out of the zero() function below. Rust contains two
/// different "selfs" where self can refer to the object
/// in memory or Self (capital S) which refers to the
/// data type of the structure. In the case below, this
/// is TrapFrame.
impl TrapFrame {
pub const fn zero() -> Self {
TrapFrame { regs: [0; 32],
@ -33,9 +49,17 @@ impl TrapFrame {
}
}
/// The global kernel trap frame stores 8 separate
/// frames -- one per CPU hart. We will switch these
/// in and out and store a dormant trap frame with
/// the process itself.
pub static mut KERNEL_TRAP_FRAME: [TrapFrame; 8] =
[TrapFrame::zero(); 8];
/// The SATP register contains three fields: mode, address space id, and
/// the first level table address (level 2 for Sv39). This function
/// helps make the 64-bit register contents based on those three
/// fields.
pub const fn build_satp(mode: SatpMode, asid: usize, addr: usize) -> usize {
(mode as usize) << 60
| (asid & 0xffff) << 44
@ -150,12 +174,22 @@ pub fn satp_read() -> usize {
}
}
/// Take a hammer to the page tables and synchronize
/// all of them. This essentially flushes the entire
/// TLB.
pub fn satp_fence(vaddr: usize, asid: usize) {
unsafe {
asm!("sfence.vma $0, $1" :: "r"(vaddr), "r"(asid));
}
}
/// Synchronize based on the address space identifier
/// This allows us to fence a particular process rather
/// than the entire TLB.
/// The RISC-V documentation calls this a TLB flush +.
/// Since there are other memory routines involved, they
/// didn't call it a TLB flush, but it is much like
/// Intel/AMD's invtlb [] instruction.
pub fn satp_fence_asid(asid: usize) {
unsafe {
asm!("sfence.vma zero, $0" :: "r"(asid));

View File

@ -23,10 +23,10 @@ const PLIC_CLAIM: usize = 0x0c20_0004;
// PCIE = [32..35]
// Get the next available interrupt. This is the "claim" process.
// The plic will automatically sort by priority and hand us the
// ID of the interrupt. For example, if the UART is interrupting
// and it's next, we will get the value 10.
/// Get the next available interrupt. This is the "claim" process.
/// The plic will automatically sort by priority and hand us the
/// ID of the interrupt. For example, if the UART is interrupting
/// and it's next, we will get the value 10.
pub fn next() -> Option<u32> {
let claim_reg = PLIC_CLAIM as *const u32;
let claim_no;
@ -41,8 +41,8 @@ pub fn next() -> Option<u32> {
}
}
// Complete a pending interrupt by id. The id should come
// from the next() function above.
/// Complete a pending interrupt by id. The id should come
/// from the next() function above.
pub fn complete(id: u32) {
let complete_reg = PLIC_CLAIM as *mut u32;
unsafe {
@ -50,10 +50,10 @@ pub fn complete(id: u32) {
}
}
// Set the global threshold. The threshold can be a value [0..7].
// The PLIC will mask any interrupts at or below the given threshold.
// This means that a threshold of 7 will mask ALL interrupts and
// a threshold of 0 will allow ALL interrupts.
/// Set the global threshold. The threshold can be a value [0..7].
/// The PLIC will mask any interrupts at or below the given threshold.
/// This means that a threshold of 7 will mask ALL interrupts and
/// a threshold of 0 will allow ALL interrupts.
pub fn set_threshold(tsh: u8) {
let actual_tsh = tsh & 7;
let tsh_reg = PLIC_THRESHOLD as *mut u32;
@ -62,7 +62,7 @@ pub fn set_threshold(tsh: u8) {
}
}
// See if a given interrupt id is pending.
/// See if a given interrupt id is pending.
pub fn is_pending(id: u32) -> bool {
let pend = PLIC_PENDING as *const u32;
let actual_id = 1 << id;
@ -73,7 +73,7 @@ pub fn is_pending(id: u32) -> bool {
actual_id & pend_ids != 0
}
// Enable a given interrupt id
/// Enable a given interrupt id
pub fn enable(id: u32) {
let enables = PLIC_INT_ENABLE as *mut u32;
let actual_id = 1 << id;
@ -82,8 +82,8 @@ pub fn enable(id: u32) {
}
}
// Set a given interrupt priority to the given priority.
// The priority must be [0..7]
/// Set a given interrupt priority to the given priority.
/// The priority must be [0..7]
pub fn set_priority(id: u32, prio: u8) {
let actual_prio = prio as u32 & 7;
let prio_reg = PLIC_PRIORITY as *mut u32;

View File

@ -6,6 +6,10 @@
use crate::cpu::TrapFrame;
#[no_mangle]
/// The m_trap stands for "machine trap". Right now, we are handling
/// all traps at machine mode. In this mode, we can figure out what's
/// going on and send a trap where it needs to be. Remember, in machine
/// mode and in this trap, interrupts are disabled and the MMU is off.
extern "C" fn m_trap(epc: usize,
tval: usize,
cause: usize,