From dcdebcd8e4f144ee285451f510d7c9aa0f969043 Mon Sep 17 00:00:00 2001 From: vhaudiquet Date: Fri, 20 Oct 2023 09:58:10 +0200 Subject: [PATCH] Added memory access type for mmu --- src/cpu/rv32cpu.c | 9 +++------ src/memory/memory.c | 35 +++++++++++++++++++++++++++++------ src/memory/memory.h | 1 + src/memory/mmu.c | 24 ++++++++++++++++++++---- src/memory/mmu.h | 9 ++++++++- 5 files changed, 61 insertions(+), 17 deletions(-) diff --git a/src/cpu/rv32cpu.c b/src/cpu/rv32cpu.c index ffe87d0..aab926a 100644 --- a/src/cpu/rv32cpu.c +++ b/src/cpu/rv32cpu.c @@ -682,7 +682,7 @@ __attribute__((noreturn)) void cpu_loop(rv32_cpu_t* cpu) { while(1) { - // Aquire CPU and memory mutex + // Aquire CPU mutex pthread_mutex_lock(&cpu0_mutex); // No simulation ticks left : wakeup people waiting on sim end @@ -692,8 +692,6 @@ __attribute__((noreturn)) void cpu_loop(rv32_cpu_t* cpu) while(!cpu->sim_ticks_left) pthread_cond_wait(&cpu0->sim_condition, &cpu0_mutex); - // pthread_mutex_lock(&memory_mutex); - // Fetch raw_instruction_t raw_instruction; if(cpu->pc > memory_size - 4) @@ -701,7 +699,7 @@ __attribute__((noreturn)) void cpu_loop(rv32_cpu_t* cpu) fprintf(stderr, "Error: instruction fetch: pc is out of addressable memory\n"); exit(EXIT_FAILURE); } - raw_instruction.data = mem_read32(cpu->pc); + raw_instruction.data = mem_fetch(cpu->pc); // Decode instruction_t instruction; @@ -726,8 +724,7 @@ __attribute__((noreturn)) void cpu_loop(rv32_cpu_t* cpu) if(cpu->sim_ticks_left != (-1)) cpu->sim_ticks_left--; - // Let go of cpu and memory mutex - // pthread_mutex_unlock(&memory_mutex); + // Let go of cpu mutex pthread_mutex_unlock(&cpu0_mutex); } } diff --git a/src/memory/memory.c b/src/memory/memory.c index a670aa9..ee5b626 100644 --- a/src/memory/memory.c +++ b/src/memory/memory.c @@ -40,7 +40,7 @@ void mem_register_mmio(uint32_t address, uint32_t reg_size, uint32_t reg_count, void mem_write8(uint32_t address, uint8_t value) { - address = mmu_resolve(cpu0, address); + address = mmu_resolve(cpu0, WRITE, address); // Look wether we are on an MMIO region struct MMIO_ENTRY* io = mmio; @@ -71,7 +71,7 @@ void mem_write8(uint32_t address, uint8_t value) void mem_write16(uint32_t address, uint16_t value) { - address = mmu_resolve(cpu0, address); + address = mmu_resolve(cpu0, WRITE, address); // Look wether we are on an MMIO region struct MMIO_ENTRY* io = mmio; @@ -102,7 +102,7 @@ void mem_write16(uint32_t address, uint16_t value) void mem_write32(uint32_t address, uint32_t value) { - address = mmu_resolve(cpu0, address); + address = mmu_resolve(cpu0, WRITE, address); // Look wether we are on an MMIO region struct MMIO_ENTRY* io = mmio; @@ -133,7 +133,7 @@ void mem_write32(uint32_t address, uint32_t value) uint8_t mem_read8(uint32_t address) { - address = mmu_resolve(cpu0, address); + address = mmu_resolve(cpu0, READ, address); // Look wether we are on an MMIO region struct MMIO_ENTRY* io = mmio; @@ -164,7 +164,7 @@ uint8_t mem_read8(uint32_t address) uint16_t mem_read16(uint32_t address) { - address = mmu_resolve(cpu0, address); + address = mmu_resolve(cpu0, READ, address); // Look wether we are on an MMIO region struct MMIO_ENTRY* io = mmio; @@ -195,7 +195,7 @@ uint16_t mem_read16(uint32_t address) uint32_t mem_read32(uint32_t address) { - address = mmu_resolve(cpu0, address); + address = mmu_resolve(cpu0, READ, address); // Look wether we are on an MMIO region struct MMIO_ENTRY* io = mmio; @@ -223,3 +223,26 @@ uint32_t mem_read32(uint32_t address) pthread_mutex_unlock(&memory_mutex); return tr; } + +uint32_t mem_fetch(uint32_t address) +{ + address = mmu_resolve(cpu0, INSTRUCTION_FETCH, address); + + // Look wether we are on an MMIO region + struct MMIO_ENTRY* io = mmio; + while(io) + { + if(MMIO_INSIDE(io, address)) + { + fprintf(stderr, "MEMORY: Trying to fetch an instruction inside an MMIO region !\n"); + exit(EXIT_FAILURE); + } + io = io->next; + } + + // Proceed with memory read + pthread_mutex_lock(&memory_mutex); + uint32_t tr = *((uint32_t*) &memory[address]); + pthread_mutex_unlock(&memory_mutex); + return tr; +} diff --git a/src/memory/memory.h b/src/memory/memory.h index 1a29d19..9f90928 100644 --- a/src/memory/memory.h +++ b/src/memory/memory.h @@ -14,5 +14,6 @@ void mem_write32(uint32_t address, uint32_t value); uint8_t mem_read8(uint32_t address); uint16_t mem_read16(uint32_t address); uint32_t mem_read32(uint32_t address); +uint32_t mem_fetch(uint32_t address); #endif diff --git a/src/memory/mmu.c b/src/memory/mmu.c index b120c91..721d834 100644 --- a/src/memory/mmu.c +++ b/src/memory/mmu.c @@ -44,7 +44,24 @@ extern uint8_t* memory; #define VADDR_VPN_0 (0x003FF000) #define VADDR_PAGE_OFFSET (0x00000FFF) -uint32_t mmu_resolve(rv32_cpu_t* cpu, uint32_t vaddr) +uint32_t mmu_scause_from_access(memory_access_type_t access_type) +{ + switch(access_type) + { + case READ: + return SCAUSE_LOAD_PAGE_FAULT; + case WRITE: + return SCAUSE_STORE_AMO_PAGE_FAULT; + case INSTRUCTION_FETCH: + return SCAUSE_INSTRUCTION_PAGE_FAULT; + default: + fprintf(stderr, "mmu_scause_from_access: invalid parameter\n"); + exit(EXIT_FAILURE); + break; + } +} + +uint32_t mmu_resolve(rv32_cpu_t* cpu, memory_access_type_t access_type, uint32_t vaddr) { // TODO: Make sure we are in S-mode or U-mode @@ -64,8 +81,7 @@ uint32_t mmu_resolve(rv32_cpu_t* cpu, uint32_t vaddr) if(!(pte & PTE_V)) { // Invalid PTE - // TODO : Add a MEMORY_ACCESS_TYPE - exception_trigger(cpu, SCAUSE_INSTRUCTION_PAGE_FAULT); + exception_trigger(cpu, mmu_scause_from_access(access_type)); } if((pte & PTE_R) || (pte & PTE_W) || (pte & PTE_X)) @@ -93,7 +109,7 @@ uint32_t mmu_resolve(rv32_cpu_t* cpu, uint32_t vaddr) if(!(pte & PTE_V)) { // Invalid PTE - exception_trigger(cpu, SCAUSE_INSTRUCTION_PAGE_FAULT); + exception_trigger(cpu, mmu_scause_from_access(access_type)); } // This must be a leaf PTE, as Sv32 only supports 2-level mappings diff --git a/src/memory/mmu.h b/src/memory/mmu.h index c2cdacf..03de7f0 100644 --- a/src/memory/mmu.h +++ b/src/memory/mmu.h @@ -4,6 +4,13 @@ #include #include "cpu/rv32cpu.h" -uint32_t mmu_resolve(rv32_cpu_t* cpu, uint32_t vaddr); +typedef enum MEMORY_ACCESS_TYPE +{ + READ, + WRITE, + INSTRUCTION_FETCH +} memory_access_type_t; + +uint32_t mmu_resolve(rv32_cpu_t* cpu, memory_access_type_t access_type, uint32_t vaddr); #endif