From 530d8c0fe4ae0bb4089898568448fb6cb5a3fcc7 Mon Sep 17 00:00:00 2001 From: Imbus <> Date: Wed, 7 Aug 2024 14:25:19 +0200 Subject: [PATCH] Extensive documentation of the architecture specific bits --- kernel/riscv.h | 194 +++++++++++++++++++++++++++++++++++++------------ 1 file changed, 146 insertions(+), 48 deletions(-) diff --git a/kernel/riscv.h b/kernel/riscv.h index 8fbeadd..ccf19eb 100644 --- a/kernel/riscv.h +++ b/kernel/riscv.h @@ -46,12 +46,25 @@ w_mepc(u64 x) // Supervisor Status Register, sstatus -#define SSTATUS_SPP (1L << 8) // Previous mode, 1=Supervisor, 0=User -#define SSTATUS_SPIE (1L << 5) // Supervisor Previous Interrupt Enable -#define SSTATUS_UPIE (1L << 4) // User Previous Interrupt Enable -#define SSTATUS_SIE (1L << 1) // Supervisor Interrupt Enable -#define SSTATUS_UIE (1L << 0) // User Interrupt Enable +/** Supervisor Previous Privilege */ +#define SSTATUS_SPP (1L << 8) // Previous mode, 1=Supervisor, 0=User +/** Supervisor Previous Interrupt Enable */ +#define SSTATUS_SPIE (1L << 5) + +/** User Previous Interrupt Enable */ +#define SSTATUS_UPIE (1L << 4) + +/** Supervisor Interrupt Enable */ +#define SSTATUS_SIE (1L << 1) + +/** User Interrupt Enable */ +#define SSTATUS_UIE (1L << 0) + +/** + * Read the value of the sstatus register. + * (Supervisor Status Register) + */ static inline u64 r_sstatus() { @@ -60,13 +73,17 @@ r_sstatus() return x; } +/** + * Write a value to the sstatus register. + * (Supervisor Status Register) + */ static inline void w_sstatus(u64 x) { asm volatile("csrw sstatus, %0" : : "r"(x)); } -// Supervisor Interrupt Pending +/** Read Suporvisor Interrupt Pending */ static inline u64 r_sip() { @@ -75,16 +92,26 @@ r_sip() return x; } +/** Write Suporvisor Interrupt Pending */ static inline void w_sip(u64 x) { asm volatile("csrw sip, %0" : : "r"(x)); } -// Supervisor Interrupt Enable -#define SIE_SEIE (1L << 9) // external -#define SIE_STIE (1L << 5) // timer -#define SIE_SSIE (1L << 1) // software +/** Supervisor External Interrup Enable */ +#define SIE_SEIE (1L << 9) + +/** Supervisor Timer Interrupt Enable */ +#define SIE_STIE (1L << 5) + +/** Supervisor Software Interrupt Enable */ +#define SIE_SSIE (1L << 1) + +/** + * Read the value of the sie register. + * (Supervisor Interrupt Enable) + */ static inline u64 r_sie() { @@ -93,16 +120,29 @@ r_sie() return x; } +/** + * Write the valie to the sie rgister + * (Supervisor Interrupt Enable) + */ static inline void w_sie(u64 x) { asm volatile("csrw sie, %0" : : "r"(x)); } -// Machine-mode Interrupt Enable -#define MIE_MEIE (1L << 11) // external -#define MIE_MTIE (1L << 7) // timer -#define MIE_MSIE (1L << 3) // software +/** Machine External Interrupt Enable */ +#define MIE_MEIE (1L << 11) + +/** Machine Timer Interrupt Enable */ +#define MIE_MTIE (1L << 7) + +/** Machine Software Interrupt Enable */ +#define MIE_MSIE (1L << 3) + +/** + * Read the value of the mie register. + * (Machine Interrupt Enable) + */ static inline u64 r_mie() { @@ -111,6 +151,10 @@ r_mie() return x; } +/** + * Write the value to the mie register. + * (Machine Interrupt Enable) + */ static inline void w_mie(u64 x) { @@ -120,12 +164,15 @@ w_mie(u64 x) // supervisor exception program counter, holds the // instruction address to which a return from // exception will go. + +/** Write Supervisor Exception Program Counter */ static inline void w_sepc(u64 x) { asm volatile("csrw sepc, %0" : : "r"(x)); } +/** Read Supervisor Exception Program Counter */ static inline u64 r_sepc() { @@ -134,7 +181,7 @@ r_sepc() return x; } -// Machine Exception Delegation +/** Read Machine Exception Delegation */ static inline u64 r_medeleg() { @@ -143,13 +190,14 @@ r_medeleg() return x; } +/** Write Machine Exception Delegation */ static inline void w_medeleg(u64 x) { asm volatile("csrw medeleg, %0" : : "r"(x)); } -// Machine Interrupt Delegation +/** Read Machine Interrupt Delegation */ static inline u64 r_mideleg() { @@ -158,20 +206,21 @@ r_mideleg() return x; } +/** Write Machine Interrupt Delegation */ static inline void w_mideleg(u64 x) { asm volatile("csrw mideleg, %0" : : "r"(x)); } -// Supervisor Trap-Vector Base Address -// low two bits are mode. +/** Write Supervisor Trap-Vector Base Address */ static inline void w_stvec(u64 x) { asm volatile("csrw stvec, %0" : : "r"(x)); } +/** Read Supervisor Trap-Vector Base Address */ static inline u64 r_stvec() { @@ -180,39 +229,50 @@ r_stvec() return x; } -// Machine-mode interrupt vector +/** Write Machine Trap-Vector Base Address */ static inline void w_mtvec(u64 x) { asm volatile("csrw mtvec, %0" : : "r"(x)); } -// Physical Memory Protection +/** Read Physical Memory Protection Configuration */ static inline void w_pmpcfg0(u64 x) { asm volatile("csrw pmpcfg0, %0" : : "r"(x)); } +/** Write Physical Memory Protection Configuration */ static inline void w_pmpaddr0(u64 x) { asm volatile("csrw pmpaddr0, %0" : : "r"(x)); } -// use riscv's sv39 page table scheme. +/** Risc-v's sv39 page table scheme. */ #define SATP_SV39 (8L << 60) +/** Make Supervisor Address Translation and Protection */ #define MAKE_SATP(pagetable) (SATP_SV39 | (((u64)pagetable) >> 12)) -// supervisor address translation and protection; -// holds the address of the page table. +/** + * Write the value to the satp register. + * (Supervisor Address Translation and Protection) + * + * This register holds the address of the page table. + */ static inline void w_satp(u64 x) { asm volatile("csrw satp, %0" : : "r"(x)); } +/** + * Read the value of the satp register. + * (Supervisor Address Translation and Protection) + * Returns the address of the page table. + */ static inline u64 r_satp() { @@ -221,13 +281,14 @@ r_satp() return x; } +/** Read Supervisor Scratch Register */ static inline void w_mscratch(u64 x) { asm volatile("csrw mscratch, %0" : : "r"(x)); } -// Supervisor Trap Cause +/** Supervisor Trap Cause */ static inline u64 r_scause() { @@ -236,7 +297,7 @@ r_scause() return x; } -// Supervisor Trap Value +/** Supervisor Trap Value */ static inline u64 r_stval() { @@ -245,13 +306,14 @@ r_stval() return x; } -// Machine-mode Counter-Enable +/** Write Machine-mode Counter-Enable Register */ static inline void w_mcounteren(u64 x) { asm volatile("csrw mcounteren, %0" : : "r"(x)); } +/** Read Machine-mode Counter-Enable Register */ static inline u64 r_mcounteren() { @@ -260,7 +322,10 @@ r_mcounteren() return x; } -// machine-mode cycle counter +/** + * Machine-mode cycle counter + * Reports the current wall-clock time from the timer device. + */ static inline u64 r_time() { @@ -269,21 +334,21 @@ r_time() return x; } -// enable device interrupts +/** Enable device interrupts */ static inline void intr_on() { w_sstatus(r_sstatus() | SSTATUS_SIE); } -// disable device interrupts +/** Disable device interrupts */ static inline void intr_off() { w_sstatus(r_sstatus() & ~SSTATUS_SIE); } -// are device interrupts enabled? +/** Are device interrupts enabled? */ static inline int intr_get() { @@ -291,6 +356,7 @@ intr_get() return (x & SSTATUS_SIE) != 0; } +/** Read stack pointer */ static inline u64 r_sp() { @@ -301,6 +367,8 @@ r_sp() // read and write tp, the thread pointer, which xv6 uses to hold // this core's hartid (core number), the index into cpus[]. + +/** Read thread pointer */ static inline u64 r_tp() { @@ -309,12 +377,14 @@ r_tp() return x; } +/** Write thread pointer */ static inline void w_tp(u64 x) { asm volatile("mv tp, %0" : : "r"(x)); } +/** Read the return address */ static inline u64 r_ra() { @@ -323,7 +393,7 @@ r_ra() return x; } -// flush the TLB. +/** Flush the TLB (Translation Lookaside Buffer) */ static inline void sfence_vma() { @@ -331,37 +401,65 @@ sfence_vma() asm volatile("sfence.vma zero, zero"); } -typedef u64 pte_t; +/** Page Table Entry Type */ +typedef u64 pte_t; + +/** Page Table Type */ typedef u64 *pagetable_t; // 512 PTEs #endif // __ASSEMBLER__ -#define PGSIZE 4096 // bytes per page -#define PGSHIFT 12 // bits of offset within a page +/** Page Size */ +#define PGSIZE 4096 // bytes per page + +/** Page Shift, bits of offset within a page */ +#define PGSHIFT 12 #define PGROUNDUP(sz) (((sz) + PGSIZE - 1) & ~(PGSIZE - 1)) #define PGROUNDDOWN(a) (((a)) & ~(PGSIZE - 1)) -#define PTE_V (1L << 0) // valid -#define PTE_R (1L << 1) -#define PTE_W (1L << 2) -#define PTE_X (1L << 3) -#define PTE_U (1L << 4) // user can access +/** + * Page Table Entry Flags + */ -// shift a physical address to the right place for a PTE. +#define PTE_V (1L << 0) /** PTE Valid */ +#define PTE_R (1L << 1) /** PTE Readable */ +#define PTE_W (1L << 2) /** PTE Writeable */ +#define PTE_X (1L << 3) /** PTE Executable */ +#define PTE_U (1L << 4) /** PTE User Accessible */ + +/** + * Helper macros to shift a physical address + * to the right place for a PTE. + */ + +/** Physical Address to Page Table Entry */ #define PA2PTE(pa) ((((u64)pa) >> 12) << 10) +/** Page Table Entry to Physical Address */ #define PTE2PA(pte) (((pte) >> 10) << 12) +/** Page Table Entry Flags */ #define PTE_FLAGS(pte) ((pte) & 0x3FF) -// extract the three 9-bit page table indices from a virtual address. -#define PXMASK 0x1FF // 9 bits -#define PXSHIFT(level) (PGSHIFT + (9 * (level))) -#define PX(level, va) ((((u64)(va)) >> PXSHIFT(level)) & PXMASK) +/** + * Helper macros to extract the three 9-bit + * page table indices from a virtual address. + */ -// one beyond the highest possible virtual address. -// MAXVA is actually one bit less than the max allowed by -// Sv39, to avoid having to sign-extend virtual addresses -// that have the high bit set. +/** Page Extract Mask */ +#define PXMASK 0x1FF // 9 bits, 0b111111111 + +/** Page Extract Shift */ +#define PXSHIFT(level) (PGSHIFT + (9 * (level))) + +/** Page Extract */ +#define PX(level, va) ((((u64)(va)) >> PXSHIFT(level)) & PXMASK) + +/** + * One beyond the highest possible virtual address. + * MAXVA is actually one bit less than the max allowed by + * Sv39, to avoid having to sign-extend virtual addresses + * that have the high bit set. + */ #define MAXVA (1L << (9 + 9 + 9 + 12 - 1))