Compare commits

...

2 Commits

  1. 81
      src/memory/memory.c
  2. 24
      src/memory/mmu.c

@ -50,7 +50,7 @@ void mem_write8(uint32_t address, uint8_t value)
{ {
if(io->reg_size == 1) if(io->reg_size == 1)
{ {
void (*fn_write)(uint32_t, uint8_t) = io->fn_write; void (*fn_write)(uint32_t, uint8_t) = io->fn_write;
fn_write(address, value); fn_write(address, value);
return; return;
} }
@ -63,6 +63,13 @@ void mem_write8(uint32_t address, uint8_t value)
io = io->next; io = io->next;
} }
// Check if we are inside of physical memory
if(address + 1 > memory_size)
{
fprintf(stderr, "MEMORY: Invalid write of size 1 outside of physical memory at address 0x%x\n", address);
exit(EXIT_FAILURE);
}
// Proceed with memory write // Proceed with memory write
pthread_mutex_lock(&memory_mutex); pthread_mutex_lock(&memory_mutex);
memory[address] = value; memory[address] = value;
@ -81,7 +88,7 @@ void mem_write16(uint32_t address, uint16_t value)
{ {
if(io->reg_size == 2) if(io->reg_size == 2)
{ {
void (*fn_write)(uint32_t, uint16_t) = io->fn_write; void (*fn_write)(uint32_t, uint16_t) = io->fn_write;
fn_write(address, value); fn_write(address, value);
return; return;
} }
@ -94,6 +101,13 @@ void mem_write16(uint32_t address, uint16_t value)
io = io->next; io = io->next;
} }
// Check if we are inside of physical memory
if(address + 2 > memory_size)
{
fprintf(stderr, "MEMORY: Invalid write of size 2 outside of physical memory at address 0x%x\n", address);
exit(EXIT_FAILURE);
}
// Proceed with memory write // Proceed with memory write
pthread_mutex_lock(&memory_mutex); pthread_mutex_lock(&memory_mutex);
*((uint16_t*) &memory[address]) = value; *((uint16_t*) &memory[address]) = value;
@ -112,7 +126,7 @@ void mem_write32(uint32_t address, uint32_t value)
{ {
if(io->reg_size == 4) if(io->reg_size == 4)
{ {
void (*fn_write)(uint32_t, uint32_t) = io->fn_write; void (*fn_write)(uint32_t, uint32_t) = io->fn_write;
fn_write(address, value); fn_write(address, value);
return; return;
} }
@ -125,6 +139,13 @@ void mem_write32(uint32_t address, uint32_t value)
io = io->next; io = io->next;
} }
// Check if we are inside of physical memory
if(address + 4 > memory_size)
{
fprintf(stderr, "MEMORY: Invalid write of size 1 outside of physical memory at address 0x%x\n", address);
exit(EXIT_FAILURE);
}
// Proceed with memory write // Proceed with memory write
pthread_mutex_lock(&memory_mutex); pthread_mutex_lock(&memory_mutex);
*((uint32_t*) &memory[address]) = value; *((uint32_t*) &memory[address]) = value;
@ -135,7 +156,7 @@ uint8_t mem_read8(uint32_t address)
{ {
address = mmu_resolve(cpu0, READ, 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;
while(io) while(io)
{ {
@ -143,7 +164,7 @@ uint8_t mem_read8(uint32_t address)
{ {
if(io->reg_size == 1) if(io->reg_size == 1)
{ {
uint8_t (*fn_read)(uint32_t) = io->fn_read; uint8_t (*fn_read)(uint32_t) = io->fn_read;
return fn_read(address); return fn_read(address);
} }
else else
@ -155,18 +176,25 @@ uint8_t mem_read8(uint32_t address)
io = io->next; io = io->next;
} }
// Check if we are inside of physical memory
if(address + 1 > memory_size)
{
fprintf(stderr, "MEMORY: Invalid read of size 1 outside of physical memory at address 0x%x\n", address);
exit(EXIT_FAILURE);
}
// Proceed with memory read // Proceed with memory read
pthread_mutex_lock(&memory_mutex); pthread_mutex_lock(&memory_mutex);
uint8_t tr = memory[address]; uint8_t tr = memory[address];
pthread_mutex_unlock(&memory_mutex); pthread_mutex_unlock(&memory_mutex);
return tr; return tr;
} }
uint16_t mem_read16(uint32_t address) uint16_t mem_read16(uint32_t address)
{ {
address = mmu_resolve(cpu0, READ, 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;
while(io) while(io)
{ {
@ -174,7 +202,7 @@ uint16_t mem_read16(uint32_t address)
{ {
if(io->reg_size == 2) if(io->reg_size == 2)
{ {
uint16_t (*fn_read)(uint32_t) = io->fn_read; uint16_t (*fn_read)(uint32_t) = io->fn_read;
return fn_read(address); return fn_read(address);
} }
else else
@ -186,18 +214,25 @@ uint16_t mem_read16(uint32_t address)
io = io->next; io = io->next;
} }
// Check if we are inside of physical memory
if(address + 2 > memory_size)
{
fprintf(stderr, "MEMORY: Invalid read of size 2 outside of physical memory at address 0x%x\n", address);
exit(EXIT_FAILURE);
}
// Proceed with memory read // Proceed with memory read
pthread_mutex_lock(&memory_mutex); pthread_mutex_lock(&memory_mutex);
uint16_t tr = *((uint16_t*) &memory[address]); uint16_t tr = *((uint16_t*) &memory[address]);
pthread_mutex_unlock(&memory_mutex); pthread_mutex_unlock(&memory_mutex);
return tr; return tr;
} }
uint32_t mem_read32(uint32_t address) uint32_t mem_read32(uint32_t address)
{ {
address = mmu_resolve(cpu0, READ, 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;
while(io) while(io)
{ {
@ -205,7 +240,7 @@ uint32_t mem_read32(uint32_t address)
{ {
if(io->reg_size == 4) if(io->reg_size == 4)
{ {
uint32_t (*fn_read)(uint32_t) = io->fn_read; uint32_t (*fn_read)(uint32_t) = io->fn_read;
return fn_read(address); return fn_read(address);
} }
else else
@ -217,18 +252,25 @@ uint32_t mem_read32(uint32_t address)
io = io->next; io = io->next;
} }
// Check if we are inside of physical memory
if(address + 4 > memory_size)
{
fprintf(stderr, "MEMORY: Invalid read of size 4 outside of physical memory at address 0x%x\n", address);
exit(EXIT_FAILURE);
}
// Proceed with memory read // Proceed with memory read
pthread_mutex_lock(&memory_mutex); pthread_mutex_lock(&memory_mutex);
uint32_t tr = *((uint32_t*) &memory[address]); uint32_t tr = *((uint32_t*) &memory[address]);
pthread_mutex_unlock(&memory_mutex); pthread_mutex_unlock(&memory_mutex);
return tr; return tr;
} }
uint32_t mem_fetch(uint32_t address) uint32_t mem_fetch(uint32_t address)
{ {
address = mmu_resolve(cpu0, INSTRUCTION_FETCH, address); address = mmu_resolve(cpu0, INSTRUCTION_FETCH, 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;
while(io) while(io)
{ {
@ -240,9 +282,16 @@ uint32_t mem_fetch(uint32_t address)
io = io->next; io = io->next;
} }
// Check if we are inside of physical memory
if(address + 4 > memory_size)
{
fprintf(stderr, "MEMORY: Invalid fetch outside of physical memory at address 0x%x\n", address);
exit(EXIT_FAILURE);
}
// Proceed with memory read // Proceed with memory read
pthread_mutex_lock(&memory_mutex); pthread_mutex_lock(&memory_mutex);
uint32_t tr = *((uint32_t*) &memory[address]); uint32_t tr = *((uint32_t*) &memory[address]);
pthread_mutex_unlock(&memory_mutex); pthread_mutex_unlock(&memory_mutex);
return tr; return tr;
} }

@ -89,6 +89,18 @@ uint32_t mmu_resolve(rv32_cpu_t* cpu, memory_access_type_t access_type, uint32_t
// Leaf PTE, we are ready to resolve the mapping // Leaf PTE, we are ready to resolve the mapping
// This is a 4 MiB megapage // This is a 4 MiB megapage
// For an execute, check if we are allowed to execute
if(access_type == INSTRUCTION_FETCH && !(pte & PTE_X))
exception_trigger(cpu, mmu_scause_from_access(access_type), vaddr);
// For a write, check if we are allowed to write
if(access_type == WRITE && !(pte & PTE_W))
exception_trigger(cpu, mmu_scause_from_access(access_type), vaddr);
// For a read, check if we are allowed to read
if(access_type == READ && !(pte & PTE_R))
exception_trigger(cpu, mmu_scause_from_access(access_type), vaddr);
// Physical Address: [PPN[1] = pte.PPN[1], PPN[0] = vaddr.VPN[0], offset] // Physical Address: [PPN[1] = pte.PPN[1], PPN[0] = vaddr.VPN[0], offset]
uint32_t paddr = 0; uint32_t paddr = 0;
paddr |= (PTE_PPN_1(pte) << 22); paddr |= (PTE_PPN_1(pte) << 22);
@ -120,6 +132,18 @@ uint32_t mmu_resolve(rv32_cpu_t* cpu, memory_access_type_t access_type, uint32_t
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
// For an execute, check if we are allowed to execute
if(access_type == INSTRUCTION_FETCH && !(pte & PTE_X))
exception_trigger(cpu, mmu_scause_from_access(access_type), vaddr);
// For a write, check if we are allowed to write
if(access_type == WRITE && !(pte & PTE_W))
exception_trigger(cpu, mmu_scause_from_access(access_type), vaddr);
// For a read, check if we are allowed to read
if(access_type == READ && !(pte & PTE_R))
exception_trigger(cpu, mmu_scause_from_access(access_type), vaddr);
// Physical Address: [PPN[1] = pte.PPN[1], PPN[0] = pte.PPN[0], offset] // Physical Address: [PPN[1] = pte.PPN[1], PPN[0] = pte.PPN[0], offset]
uint32_t paddr = 0; uint32_t paddr = 0;
paddr |= (PTE_PPN_1(pte) << 22); paddr |= (PTE_PPN_1(pte) << 22);

Loading…
Cancel
Save