From 9c3dc94bd74b5062d4528a7d936bf1da2f6255e4 Mon Sep 17 00:00:00 2001 From: Garen Tyler Date: Sun, 15 Oct 2023 13:16:35 -0600 Subject: [PATCH] Implement all asm instructions in riscv.h --- kernel/rustkernel/src/riscv.rs | 190 --------------------- kernel/rustkernel/src/riscv/asm.rs | 254 +++++++++++++++++++++++++++++ kernel/rustkernel/src/riscv/mod.rs | 52 ++++++ 3 files changed, 306 insertions(+), 190 deletions(-) delete mode 100644 kernel/rustkernel/src/riscv.rs create mode 100644 kernel/rustkernel/src/riscv/asm.rs create mode 100644 kernel/rustkernel/src/riscv/mod.rs diff --git a/kernel/rustkernel/src/riscv.rs b/kernel/rustkernel/src/riscv.rs deleted file mode 100644 index d934fa1..0000000 --- a/kernel/rustkernel/src/riscv.rs +++ /dev/null @@ -1,190 +0,0 @@ -use core::arch::asm; - -pub type Pte = u64; -pub type Pagetable = *mut [Pte; 512]; - -/// Previous mode -pub const MSTATUS_MPP_MASK: u64 = 3 << 11; -pub const MSTATUS_MPP_M: u64 = 3 << 11; -pub const MSTATUS_MPP_S: u64 = 1 << 11; -pub const MSTATUS_MPP_U: u64 = 0 << 11; -/// Machine-mode interrupt enable. -pub const MSTATUS_MIE: u64 = 1 << 3; - -/// Previous mode: 1 = Supervisor, 0 = User -pub const SSTATUS_SPP: u64 = 1 << 8; -/// Supervisor Previous Interrupt Enable -pub const SSTATUS_SPIE: u64 = 1 << 5; -/// User Previous Interrupt Enable -pub const SSTATUS_UPIE: u64 = 1 << 4; -/// Supervisor Interrupt Enable -pub const SSTATUS_SIE: u64 = 1 << 1; -/// User Interrupt Enable -pub const SSTATUS_UIE: u64 = 1 << 0; - -/// Supervisor External Interrupt Enable -pub const SIE_SEIE: u64 = 1 << 9; -/// Supervisor Timer Interrupt Enable -pub const SIE_STIE: u64 = 1 << 5; -/// Supervisor Software Interrupt Enable -pub const SIE_SSIE: u64 = 1 << 1; - -/// Machine-mode External Interrupt Enable -pub const MIE_MEIE: u64 = 1 << 11; -/// Machine-mode Timer Interrupt Enable -pub const MIE_MTIE: u64 = 1 << 7; -/// Machine-mode Software Interrupt Enable -pub const MIE_MSIE: u64 = 1 << 3; - -pub const SATP_SV39: u64 = 8 << 60; - -/// Bytes per page -pub const PGSIZE: u64 = 4096; -/// Bits of offset within a page -pub const PGSHIFT: u64 = 12; - -pub const PTE_V: u64 = 1 << 0; -pub const PTE_R: u64 = 1 << 1; -pub const PTE_W: u64 = 1 << 2; -pub const PTE_X: u64 = 1 << 3; -pub const PTE_U: u64 = 1 << 4; - -/// Which hart (core) is this? -#[inline(always)] -pub unsafe fn r_mhartid() -> u64 { - let x: u64; - asm!("csrr {}, mhartid", out(reg) x); - x -} - -#[inline(always)] -pub unsafe fn r_tp() -> u64 { - let x: u64; - asm!("mv {}, tp", out(reg) x); - x -} - -#[inline(always)] -pub unsafe fn w_sstatus(x: u64) { - asm!("csrw sstatus, {}", in(reg) x); -} - -#[inline(always)] -pub unsafe fn r_sstatus() -> u64 { - let x: u64; - asm!("csrr {}, sstatus", out(reg) x); - x -} - -#[inline(always)] -pub unsafe fn intr_on() { - w_sstatus(r_sstatus() | SSTATUS_SIE); -} - -#[inline(always)] -pub unsafe fn intr_off() { - w_sstatus(r_sstatus() & !SSTATUS_SIE); -} - -#[inline(always)] -pub unsafe fn intr_get() -> i32 { - if (r_sstatus() & SSTATUS_SIE) > 0 { - 1 - } else { - 0 - } -} - -extern "C" { - /// Which hart (core) is this? - pub fn rv_r_mhartid() -> u64; - - // Machine Status Register, mstatus - pub fn r_mstatus() -> u64; - pub fn w_mstatus(x: u64); - - // Machine Exception Program Counter - // MEPC holds the instruction address to which a return from exception will go. - pub fn w_mepc(x: u64); - - // Supervisor Status Register, sstatus - pub fn rv_r_sstatus() -> u64; - pub fn rv_w_sstatus(x: u64); - - // Supervisor Interrupt Pending - pub fn r_sip() -> u64; - pub fn w_sip(x: u64); - - // Supervisor Interrupt Enable - pub fn r_sie() -> u64; - pub fn w_sie(x: u64); - - // Machine-mode Interrupt Enable - pub fn r_mie() -> u64; - pub fn w_mie(x: u64); - - // Supervisor Exception Program Counter - // SEPC holds the instruction address to which a return from exception will go. - pub fn r_sepc() -> u64; - pub fn w_sepc(x: u64); - - // Machine Exception Deletgation - pub fn r_medeleg() -> u64; - pub fn w_medeleg(x: u64); - - // Machine Interrupt Deletgation - pub fn r_mideleg() -> u64; - pub fn w_mideleg(x: u64); - - // Supervisor Trap-Vector Base Address - pub fn r_stvec() -> u64; - pub fn w_stvec(x: u64); - - // Machine-mode Interrupt Vector - pub fn w_mtvec(x: u64); - - // Physical Memory Protection - pub fn w_pmpcfg0(x: u64); - pub fn w_pmpaddr0(x: u64); - - // Supervisor Address Translation and Protection - // SATP holds the address of the page table. - pub fn r_satp() -> u64; - pub fn w_satp(x: u64); - - pub fn w_mscratch(x: u64); - - // Supervisor Trap Cause - pub fn r_scause() -> u64; - - // Supervisor Trap Value - pub fn r_stval() -> u64; - - // Machine-mode Counter-Enable - pub fn r_mcounteren() -> u64; - pub fn w_mcounteren(x: u64); - - // Machine-mode cycle counter - pub fn r_time() -> u64; - - // /// Enable device interrupts - // pub fn intr_on(); - - // /// Disable device interrupts - // pub fn intr_off(); - - // // Are device interrupts enabled? - // pub fn intr_get() -> i32; - - pub fn r_sp() -> u64; - - // Read and write TP (thread pointer), which xv6 uses - // to hold this core's hartid, the index into cpus[]. - // pub fn rv_r_tp() -> u64; - pub fn w_tp(x: u64); - - pub fn r_ra() -> u64; - - /// Flush the TLB. - pub fn sfence_vma(); -} diff --git a/kernel/rustkernel/src/riscv/asm.rs b/kernel/rustkernel/src/riscv/asm.rs new file mode 100644 index 0000000..de85023 --- /dev/null +++ b/kernel/rustkernel/src/riscv/asm.rs @@ -0,0 +1,254 @@ +use super::*; +use core::arch::asm; + +/// Which hart (core) is this? +#[inline(always)] +pub unsafe fn r_mhartid() -> u64 { + let x: u64; + asm!("csrr {}, mhartid", out(reg) x); + x +} + +// Machine Status Register, mstatus +#[inline(always)] +pub unsafe fn r_mstatus() -> u64 { + let x: u64; + asm!("csrr {}, mstatus", out(reg) x); + x +} +#[inline(always)] +pub unsafe fn w_mstatus(x: u64) { + asm!("csrw mstatus, {}", in(reg) x); +} + +// Machine Exception Program Counter +// MEPC holds the instruction address to which a return from exception will go. +#[inline(always)] +pub unsafe fn w_mepc(x: u64) { + asm!("csrw mepc, {}", in(reg) x); +} + +// Supervisor Status Register, sstatus +#[inline(always)] +pub unsafe fn r_sstatus() -> u64 { + let x: u64; + asm!("csrr {}, sstatus", out(reg) x); + x +} +#[inline(always)] +pub unsafe fn w_sstatus(x: u64) { + asm!("csrw sstatus, {}", in(reg) x); +} + +// Supervisor Interrupt Pending +#[inline(always)] +pub unsafe fn r_sip() -> u64 { + let x: u64; + asm!("csrr {}, sip", out(reg) x); + x +} +#[inline(always)] +pub unsafe fn w_sip(x: u64) { + asm!("csrw sip, {}", in(reg) x); +} + +// Supervisor Interrupt Enable +#[inline(always)] +pub unsafe fn r_sie() -> u64 { + let x: u64; + asm!("csrr {}, sie", out(reg) x); + x +} +#[inline(always)] +pub unsafe fn w_sie(x: u64) { + asm!("csrw sie, {}", in(reg) x); +} + +// Machine-mode Interrupt Enable +#[inline(always)] +pub unsafe fn r_mie() -> u64 { + let x: u64; + asm!("csrr {}, mie", out(reg) x); + x +} +#[inline(always)] +pub unsafe fn w_mie(x: u64) { + asm!("csrw mie, {}", in(reg) x); +} + +// Supervisor Exception Program Counter +// SEPC holds the instruction address to which a return from exception will go. +#[inline(always)] +pub unsafe fn r_sepc() -> u64 { + let x: u64; + asm!("csrr {}, sepc", out(reg) x); + x +} +#[inline(always)] +pub unsafe fn w_sepc(x: u64) { + asm!("csrw sepc, {}", in(reg) x); +} + +// Machine Exception Delegation +#[inline(always)] +pub unsafe fn r_medeleg() -> u64 { + let x: u64; + asm!("csrr {}, medeleg", out(reg) x); + x +} +#[inline(always)] +pub unsafe fn w_medeleg(x: u64) { + asm!("csrw medeleg, {}", in(reg) x); +} + +// Machine Interrupt Delegation +#[inline(always)] +pub unsafe fn r_mideleg() -> u64 { + let x: u64; + asm!("csrr {}, mideleg", out(reg) x); + x +} +#[inline(always)] +pub unsafe fn w_mideleg(x: u64) { + asm!("csrw mideleg, {}", in(reg) x); +} + +// Supervisor Trap-Vector Base Address +#[inline(always)] +pub unsafe fn r_stvec() -> u64 { + let x: u64; + asm!("csrr {}, stvec", out(reg) x); + x +} +#[inline(always)] +pub unsafe fn w_stvec(x: u64) { + asm!("csrw stvec, {}", in(reg) x); +} + +// Machine-mode Interrupt Vector +#[inline(always)] +pub unsafe fn w_mtvec(x: u64) { + asm!("csrw mtvec, {}", in(reg) x); +} + +// Physical Memory Protection +#[inline(always)] +pub unsafe fn w_pmpcfg0(x: u64) { + asm!("csrw pmpcfg0, {}", in(reg) x); +} +#[inline(always)] +pub unsafe fn w_pmpaddr0(x: u64) { + asm!("csrw pmpaddr0, {}", in(reg) x); +} + +// Supervisor Address Translation and Protection +// SATP holds the address of the page table. +#[inline(always)] +pub unsafe fn r_satp() -> u64 { + let x: u64; + asm!("csrr {}, satp", out(reg) x); + x +} +#[inline(always)] +pub unsafe fn w_satp(x: u64) { + asm!("csrw satp, {}", in(reg) x); +} + +#[inline(always)] +pub unsafe fn w_mscratch(x: u64) { + asm!("csrw mscratch, {}", in(reg) x); +} + + +// Supervisor Trap Cause +#[inline(always)] +pub unsafe fn r_scause() -> u64 { + let x: u64; + asm!("csrr {}, scause", out(reg) x); + x +} + +// Supervisor Trap Value +#[inline(always)] +pub unsafe fn r_stval() -> u64 { + let x: u64; + asm!("csrr {}, stval", out(reg) x); + x +} + +// Machine-mode Counter-Enable +#[inline(always)] +pub unsafe fn r_mcounteren() -> u64 { + let x: u64; + asm!("csrr {}, mcounteren", out(reg) x); + x +} +#[inline(always)] +pub unsafe fn w_mcounteren(x: u64) { + asm!("csrw mcounteren, {}", in(reg) x); +} + +// Machine-mode cycle counter +#[inline(always)] +pub unsafe fn r_time() -> u64 { + let x: u64; + asm!("csrr {}, time", out(reg) x); + x +} + +// Enable device interrupts +#[inline(always)] +pub unsafe fn intr_on() { + w_sstatus(r_sstatus() | SSTATUS_SIE); +} + +// Disable device interrupts +#[inline(always)] +pub unsafe fn intr_off() { + w_sstatus(r_sstatus() & !SSTATUS_SIE); +} + +// Are device interrupts enabled? +#[inline(always)] +pub unsafe fn intr_get() -> i32 { + if (r_sstatus() & SSTATUS_SIE) > 0 { + 1 + } else { + 0 + } +} + +#[inline(always)] +pub unsafe fn r_sp() -> u64 { + let x: u64; + asm!("mv {}, sp", out(reg) x); + x +} + +// Read and write TP (thread pointer), which xv6 uses +// to hold this core's hartid, the index into cpus[]. +// pub fn rv_r_tp() -> u64; +#[inline(always)] +pub unsafe fn r_tp() -> u64 { + let x: u64; + asm!("mv {}, tp", out(reg) x); + x +} +#[inline(always)] +pub unsafe fn w_tp(x: u64) { + asm!("mv tp, {}", in(reg) x); +} + +#[inline(always)] +pub unsafe fn r_ra() -> u64 { + let x: u64; + asm!("mv {}, ra", out(reg) x); + x +} + +// Flush the TLB. +#[inline(always)] +pub unsafe fn sfence_vma() { + // The "zero, zero" means flush all TLB entries. + asm!("sfence.vma zero, zero"); +} diff --git a/kernel/rustkernel/src/riscv/mod.rs b/kernel/rustkernel/src/riscv/mod.rs new file mode 100644 index 0000000..b5ab51d --- /dev/null +++ b/kernel/rustkernel/src/riscv/mod.rs @@ -0,0 +1,52 @@ +pub mod asm; + +pub use asm::*; + +pub type Pte = u64; +pub type Pagetable = *mut [Pte; 512]; + +/// Previous mode +pub const MSTATUS_MPP_MASK: u64 = 3 << 11; +pub const MSTATUS_MPP_M: u64 = 3 << 11; +pub const MSTATUS_MPP_S: u64 = 1 << 11; +pub const MSTATUS_MPP_U: u64 = 0 << 11; +/// Machine-mode interrupt enable. +pub const MSTATUS_MIE: u64 = 1 << 3; + +/// Previous mode: 1 = Supervisor, 0 = User +pub const SSTATUS_SPP: u64 = 1 << 8; +/// Supervisor Previous Interrupt Enable +pub const SSTATUS_SPIE: u64 = 1 << 5; +/// User Previous Interrupt Enable +pub const SSTATUS_UPIE: u64 = 1 << 4; +/// Supervisor Interrupt Enable +pub const SSTATUS_SIE: u64 = 1 << 1; +/// User Interrupt Enable +pub const SSTATUS_UIE: u64 = 1 << 0; + +/// Supervisor External Interrupt Enable +pub const SIE_SEIE: u64 = 1 << 9; +/// Supervisor Timer Interrupt Enable +pub const SIE_STIE: u64 = 1 << 5; +/// Supervisor Software Interrupt Enable +pub const SIE_SSIE: u64 = 1 << 1; + +/// Machine-mode External Interrupt Enable +pub const MIE_MEIE: u64 = 1 << 11; +/// Machine-mode Timer Interrupt Enable +pub const MIE_MTIE: u64 = 1 << 7; +/// Machine-mode Software Interrupt Enable +pub const MIE_MSIE: u64 = 1 << 3; + +pub const SATP_SV39: u64 = 8 << 60; + +/// Bytes per page +pub const PGSIZE: u64 = 4096; +/// Bits of offset within a page +pub const PGSHIFT: u64 = 12; + +pub const PTE_V: u64 = 1 << 0; +pub const PTE_R: u64 = 1 << 1; +pub const PTE_W: u64 = 1 << 2; +pub const PTE_X: u64 = 1 << 3; +pub const PTE_U: u64 = 1 << 4;