Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ include arch/$(ARCH)/build.mk
INC_DIRS += -I $(SRC_DIR)/include \
-I $(SRC_DIR)/include/lib

KERNEL_OBJS := timer.o mqueue.o pipe.o semaphore.o mutex.o error.o syscall.o task.o main.o
KERNEL_OBJS := timer.o mqueue.o pipe.o semaphore.o mutex.o error.o syscall.o task.o memprot.o main.o
KERNEL_OBJS := $(addprefix $(BUILD_KERNEL_DIR)/,$(KERNEL_OBJS))
deps += $(KERNEL_OBJS:%.o=%.o.d)

Expand Down
2 changes: 1 addition & 1 deletion arch/riscv/build.mk
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ LDFLAGS += --gc-sections
ARFLAGS = r
LDSCRIPT = $(ARCH_DIR)/riscv32-qemu.ld

HAL_OBJS := boot.o hal.o muldiv.o
HAL_OBJS := boot.o hal.o muldiv.o pmp.o
HAL_OBJS := $(addprefix $(BUILD_KERNEL_DIR)/,$(HAL_OBJS))
deps += $(HAL_OBJS:%.o=%.o.d)

Expand Down
79 changes: 79 additions & 0 deletions arch/riscv/csr.h
Original file line number Diff line number Diff line change
Expand Up @@ -179,3 +179,82 @@

/* Machine Scratch Register - For temporary storage during traps */
#define CSR_MSCRATCH 0x340

/* PMP Address Registers (pmpaddr0-pmpaddr15) - 16 regions maximum
* In TOR (Top-of-Range) mode, these define the upper boundary of each region.
* The lower boundary is defined by the previous region's upper boundary.
*/
#define CSR_PMPADDR0 0x3b0
#define CSR_PMPADDR1 0x3b1
#define CSR_PMPADDR2 0x3b2
#define CSR_PMPADDR3 0x3b3
#define CSR_PMPADDR4 0x3b4
#define CSR_PMPADDR5 0x3b5
#define CSR_PMPADDR6 0x3b6
#define CSR_PMPADDR7 0x3b7
#define CSR_PMPADDR8 0x3b8
#define CSR_PMPADDR9 0x3b9
#define CSR_PMPADDR10 0x3ba
#define CSR_PMPADDR11 0x3bb
#define CSR_PMPADDR12 0x3bc
#define CSR_PMPADDR13 0x3bd
#define CSR_PMPADDR14 0x3be
#define CSR_PMPADDR15 0x3bf

/* PMP Configuration Registers (pmpcfg0-pmpcfg3)
* Each configuration register controls 4 PMP regions (on RV32).
* pmpcfg0 controls pmpaddr0-3, pmpcfg1 controls pmpaddr4-7, etc.
*/
#define CSR_PMPCFG0 0x3a0
#define CSR_PMPCFG1 0x3a1
#define CSR_PMPCFG2 0x3a2
#define CSR_PMPCFG3 0x3a3

/* PMP Configuration Field Bits (8 bits per region within pmpcfg)
* Layout in each byte of pmpcfg:
* Bit 7: L (Lock) - Locks this region until hardware reset
* Bits 6-5: Reserved
* Bits 4-3: A (Address Matching Mode)
* Bit 2: X (Execute permission)
* Bit 1: W (Write permission)
* Bit 0: R (Read permission)
*/

/* Lock bit: Prevents further modification of this region */
#define PMPCFG_L (1U << 7)

/* Address Matching Mode (bits 3-4)
* Choose TOR mode for no alignment requirements on region sizes, and support
* for arbitrary address ranges.
*/
#define PMPCFG_A_SHIFT 3
#define PMPCFG_A_MASK (0x3U << PMPCFG_A_SHIFT)
#define PMPCFG_A_OFF (0x0U << PMPCFG_A_SHIFT) /* Null region (disabled) */
#define PMPCFG_A_TOR (0x1U << PMPCFG_A_SHIFT) /* Top-of-Range mode */

/* Permission bits */
#define PMPCFG_X (1U << 2) /* Execute permission */
#define PMPCFG_W (1U << 1) /* Write permission */
#define PMPCFG_R (1U << 0) /* Read permission */

/* Common permission combinations */
#define PMPCFG_PERM_NONE (0x0U) /* No access */
#define PMPCFG_PERM_R (PMPCFG_R) /* Read-only */
#define PMPCFG_PERM_RW (PMPCFG_R | PMPCFG_W) /* Read-Write */
#define PMPCFG_PERM_X (PMPCFG_X) /* Execute-only */
#define PMPCFG_PERM_RX (PMPCFG_R | PMPCFG_X) /* Read-Execute */
#define PMPCFG_PERM_RWX (PMPCFG_R | PMPCFG_W | PMPCFG_X) /* All access */

/* Utility macros for PMP configuration manipulation */

/* Extract PMP address matching mode */
#define PMPCFG_GET_A(cfg) (((cfg) & PMPCFG_A_MASK) >> PMPCFG_A_SHIFT)

/* Extract permission bits from configuration byte */
#define PMPCFG_GET_PERM(cfg) ((cfg) & (PMPCFG_R | PMPCFG_W | PMPCFG_X))

/* Check if region is locked */
#define PMPCFG_IS_LOCKED(cfg) (((cfg) & PMPCFG_L) != 0)

/* Check if region is enabled (address mode is not OFF) */
#define PMPCFG_IS_ENABLED(cfg) (PMPCFG_GET_A(cfg) != PMPCFG_A_OFF)
7 changes: 7 additions & 0 deletions arch/riscv/hal.c
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#include <sys/task.h>

#include "csr.h"
#include "pmp.h"
#include "private/stdio.h"
#include "private/utils.h"

Expand Down Expand Up @@ -294,6 +295,12 @@ void do_trap(uint32_t cause, uint32_t epc)
const char *reason = "Unknown exception";
if (code < ARRAY_SIZE(exc_msg) && exc_msg[code])
reason = exc_msg[code];

/* Attempt to recover PMP access faults */
if ((code == 5 || code == 7) && pmp_handle_access_fault(epc, code == 7) == 0)
return;

/* All other exceptions are fatal */
printf("[EXCEPTION] code=%u (%s), epc=%08x, cause=%08x\n", code, reason,
epc, cause);
hal_panic();
Expand Down
31 changes: 28 additions & 3 deletions arch/riscv/hal.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,14 @@
#include <types.h>

/* Symbols from the linker script, defining memory boundaries */
extern uint32_t _stack_start, _stack_end; /* Start/end of the STACK memory */
extern uint32_t _heap_start, _heap_end; /* Start/end of the HEAP memory */
extern uint32_t _heap_size; /* Size of HEAP memory */
extern uint32_t _stext, _etext; /* Start/end of the .text section */
extern uint32_t _sidata; /* Start address for .data initialization */
extern uint32_t _sdata, _edata; /* Start/end address for .data section */
extern uint32_t _sbss, _ebss; /* Start/end address for .bss section */
extern uint32_t _end; /* End of kernel image */
extern uint32_t _heap_start, _heap_end; /* Start/end of the HEAP memory */
extern uint32_t _heap_size; /* Size of HEAP memory */
extern uint32_t _stack_bottom, _stack_top; /* Bottom/top of the STACK memory */

/* Read a RISC-V Control and Status Register (CSR).
* @reg : The symbolic name of the CSR (e.g., mstatus).
Expand All @@ -27,6 +28,25 @@ extern uint32_t _end; /* End of kernel image */
*/
#define write_csr(reg, val) ({ asm volatile("csrw " #reg ", %0" ::"rK"(val)); })

/* Read CSR by numeric address (for dynamic register selection).
* Used when CSR number is not known at compile-time (e.g., PMP registers).
* @csr_num : CSR address as a compile-time constant.
*/
#define read_csr_num(csr_num) \
({ \
uint32_t __tmp; \
asm volatile("csrr %0, %1" : "=r"(__tmp) : "i"(csr_num)); \
__tmp; \
})

/* Write CSR by numeric address (for dynamic register selection).
* Used when CSR number is not known at compile-time (e.g., PMP registers).
* @csr_num : CSR address as a compile-time constant.
* @val : The 32-bit value to write.
*/
#define write_csr_num(csr_num, val) \
({ asm volatile("csrw %0, %1" :: "i"(csr_num), "rK"(val)); })

/* Globally enable or disable machine-level interrupts by setting mstatus.MIE.
* @enable : Non-zero to enable, zero to disable.
* Returns the previous state of the interrupt enable bit (1 if enabled, 0 if
Expand Down Expand Up @@ -110,3 +130,8 @@ void hal_cpu_idle(void);

/* Default stack size for new tasks if not otherwise specified */
#define DEFAULT_STACK_SIZE 4096

/* Physical Memory Protection (PMP) region limit constants */
#define PMP_MAX_REGIONS 16 /* RISC-V supports 16 PMP regions */
#define PMP_TOR_PAIRS 8 /* In TOR mode, 16 regions = 8 pairs (uses 2 addrs each) */
#define MIN_PMP_REGION_SIZE 4 /* Minimum addressable size in TOR mode (4 bytes) */
Loading
Loading