Added memory access type for mmu

master
vhaudiquet 1 year ago
parent 5bb973e8da
commit dcdebcd8e4
  1. 9
      src/cpu/rv32cpu.c
  2. 35
      src/memory/memory.c
  3. 1
      src/memory/memory.h
  4. 24
      src/memory/mmu.c
  5. 9
      src/memory/mmu.h

@ -682,7 +682,7 @@ __attribute__((noreturn)) void cpu_loop(rv32_cpu_t* cpu)
{ {
while(1) while(1)
{ {
// Aquire CPU and memory mutex // Aquire CPU mutex
pthread_mutex_lock(&cpu0_mutex); pthread_mutex_lock(&cpu0_mutex);
// No simulation ticks left : wakeup people waiting on sim end // 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) while(!cpu->sim_ticks_left)
pthread_cond_wait(&cpu0->sim_condition, &cpu0_mutex); pthread_cond_wait(&cpu0->sim_condition, &cpu0_mutex);
// pthread_mutex_lock(&memory_mutex);
// Fetch // Fetch
raw_instruction_t raw_instruction; raw_instruction_t raw_instruction;
if(cpu->pc > memory_size - 4) 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"); fprintf(stderr, "Error: instruction fetch: pc is out of addressable memory\n");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
raw_instruction.data = mem_read32(cpu->pc); raw_instruction.data = mem_fetch(cpu->pc);
// Decode // Decode
instruction_t instruction; instruction_t instruction;
@ -726,8 +724,7 @@ __attribute__((noreturn)) void cpu_loop(rv32_cpu_t* cpu)
if(cpu->sim_ticks_left != (-1)) if(cpu->sim_ticks_left != (-1))
cpu->sim_ticks_left--; cpu->sim_ticks_left--;
// Let go of cpu and memory mutex // Let go of cpu mutex
// pthread_mutex_unlock(&memory_mutex);
pthread_mutex_unlock(&cpu0_mutex); pthread_mutex_unlock(&cpu0_mutex);
} }
} }

@ -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) 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 // Look wether we are on an MMIO region
struct MMIO_ENTRY* io = mmio; 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) 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 // Look wether we are on an MMIO region
struct MMIO_ENTRY* io = mmio; 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) 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 // Look wether we are on an MMIO region
struct MMIO_ENTRY* io = mmio; 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) 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 // Look wether we are on an MMIO region
struct MMIO_ENTRY* io = mmio; struct MMIO_ENTRY* io = mmio;
@ -164,7 +164,7 @@ uint8_t mem_read8(uint32_t address)
uint16_t mem_read16(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 // Look wether we are on an MMIO region
struct MMIO_ENTRY* io = mmio; struct MMIO_ENTRY* io = mmio;
@ -195,7 +195,7 @@ uint16_t mem_read16(uint32_t address)
uint32_t mem_read32(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 // Look wether we are on an MMIO region
struct MMIO_ENTRY* io = mmio; struct MMIO_ENTRY* io = mmio;
@ -223,3 +223,26 @@ uint32_t mem_read32(uint32_t address)
pthread_mutex_unlock(&memory_mutex); pthread_mutex_unlock(&memory_mutex);
return tr; 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;
}

@ -14,5 +14,6 @@ void mem_write32(uint32_t address, uint32_t value);
uint8_t mem_read8(uint32_t address); uint8_t mem_read8(uint32_t address);
uint16_t mem_read16(uint32_t address); uint16_t mem_read16(uint32_t address);
uint32_t mem_read32(uint32_t address); uint32_t mem_read32(uint32_t address);
uint32_t mem_fetch(uint32_t address);
#endif #endif

@ -44,7 +44,24 @@ extern uint8_t* memory;
#define VADDR_VPN_0 (0x003FF000) #define VADDR_VPN_0 (0x003FF000)
#define VADDR_PAGE_OFFSET (0x00000FFF) #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 // 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)) if(!(pte & PTE_V))
{ {
// Invalid PTE // Invalid PTE
// TODO : Add a MEMORY_ACCESS_TYPE exception_trigger(cpu, mmu_scause_from_access(access_type));
exception_trigger(cpu, SCAUSE_INSTRUCTION_PAGE_FAULT);
} }
if((pte & PTE_R) || (pte & PTE_W) || (pte & PTE_X)) 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)) if(!(pte & PTE_V))
{ {
// Invalid PTE // 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 // This must be a leaf PTE, as Sv32 only supports 2-level mappings

@ -4,6 +4,13 @@
#include <stdint.h> #include <stdint.h>
#include "cpu/rv32cpu.h" #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 #endif

Loading…
Cancel
Save