Skip to content

Commit

Permalink
Add BIOS support for ITLB page fault handling
Browse files Browse the repository at this point in the history
  • Loading branch information
fallen committed Jun 12, 2012
1 parent 3d8f348 commit 4225524
Show file tree
Hide file tree
Showing 7 changed files with 125 additions and 29 deletions.
16 changes: 16 additions & 0 deletions software/include/hal/mmu.h
Expand Up @@ -62,6 +62,22 @@ struct mmu_mapping {
"xor r0, r0, r0":::"r11"); \
} while(0);

#define enable_itlb() do { \
asm volatile ("xor r11, r11, r11\n\t" \
"ori r11, r11, 0x10\n\t" \
"wcsr tlbctrl, r11\n\t" \
"xor r0, r0, r0":::"r11"); \
} while(0);

#define disable_itlb() do { \
asm volatile ("xor r11, r11, r11\n\t" \
"ori r11, r11, 0x8\n\t" \
"wcsr tlbctrl, r11\n\t" \
"xor r0, r0, r0\n\t" \
"xor r0, r0, r0\n\t" \
"xor r0, r0, r0":::"r11"); \
} while(0);

void mmu_dtlb_map(unsigned int vpfn, unsigned int pfn);

#endif
2 changes: 1 addition & 1 deletion software/mmu-bios/Makefile
@@ -1,7 +1,7 @@
MMDIR=../..
include $(MMDIR)/software/include.mak

OBJECTS=crt0.o main.o dtlb_load_test.o mmu.o isr.o vsnprintf-nofloat.o dtlb_miss_handler.o dtlb_exception_handling_tests.o
OBJECTS=crt0.o main.o dtlb_load_test.o mmu.o isr.o vsnprintf-nofloat.o tlb_miss_handler.o dtlb_exception_handling_tests.o
SEGMENTS=-j .text -j .data -j .rodata

all: bios.bin
Expand Down
9 changes: 9 additions & 0 deletions software/mmu-bios/crt0.S
Expand Up @@ -119,6 +119,15 @@ _dtlb_miss_exception_handler:
nop
nop

_itlb_miss_exception_handler:
sw (sp+0), ra
calli .save_all
calli itlb_miss_handler
bi .restore_all_and_eret
nop
nop
nop

macaddress:
.byte 0x10
.byte 0xe2
Expand Down
26 changes: 0 additions & 26 deletions software/mmu-bios/dtlb_miss_handler.c

This file was deleted.

14 changes: 13 additions & 1 deletion software/mmu-bios/main.c
@@ -1,6 +1,8 @@
#include "main.h"
#include <base/mmu.h>

extern void call_function_with_itlb_enabled(void (*f)(void));

void uart_write(char c)
{
unsigned int oldmask;
Expand Down Expand Up @@ -74,7 +76,7 @@ int printf(const char *fmt, ...)

void f(void) {
CSR_UART_RXTX = '@';
asm volatile("bi f" ::: ); // We intinitely loop to f()
// asm volatile("bi f" ::: ); // We intinitely loop to f()
asm volatile("xor r0, r0, r0\n\t"
"xor r0, r0, r0" ::: );
}
Expand All @@ -92,9 +94,15 @@ void itlbtest(void) {
f_addr = 0x44004000;
printf("Mapping f() into virtual memory at 0x%08X [physical == 0x%08X]\n", f_addr, f_addr+0x1000);

mmu_map(0x44003000, 0x44003000, DTLB_MAPPING | MAPPING_CAN_READ | MAPPING_CAN_WRITE);
mmu_map(stack, stack, DTLB_MAPPING | MAPPING_CAN_READ | MAPPING_CAN_WRITE);
mmu_map(f_addr, f_addr + 0x1000, ITLB_MAPPING | MAPPING_CAN_READ);
mmu_map(itlbtest, itlbtest, ITLB_MAPPING | MAPPING_CAN_READ);
mmu_map(call_function_with_itlb_enabled, call_function_with_itlb_enabled, ITLB_MAPPING | MAPPING_CAN_READ);
puts("Mapping DONE");

mmu_itlb_invalidate(f_addr);

// We copy f's code to 0x44005000
for (p = f, pdest = 0x44005000 ; p < f + 0x1000 ; p++, pdest++)
*pdest = *p;
Expand All @@ -105,7 +113,11 @@ void itlbtest(void) {
puts("Instruction and Data caches have been invalidated");

call_function_with_itlb_enabled(f_addr);
disable_dtlb();
disable_itlb();
puts("Call DONE");
while(1)
asm volatile("xor r0, r0, r0");
}

int main(int argc, char **argv)
Expand Down
37 changes: 36 additions & 1 deletion software/mmu-bios/mmu.c
Expand Up @@ -47,6 +47,16 @@ inline void mmu_dtlb_invalidate(unsigned int vaddr)
"wcsr tlbctrl, r11":::"r11");
}

inline void mmu_itlb_invalidate(unsigned int vaddr)
{
asm volatile ("ori %0, %0, 0\n\t"
"wcsr tlbvaddr, %0"::"r"(vaddr):);

asm volatile ("xor r11, r11, r11\n\t"
"ori r11, r11, 0x20\n\t"
"wcsr tlbctrl, r11":::"r11");
}

struct mmu_mapping mappings[MAX_MMU_SLOTS];


Expand Down Expand Up @@ -102,7 +112,7 @@ unsigned int mmu_map(unsigned int vaddr, unsigned int paddr, char metadata) {
}

unsigned int get_mmu_mapping_for(unsigned int vaddr) {
int i;
unsigned int i;
vaddr = get_pfn(vaddr);

for (i = 0 ; i < MAX_MMU_SLOTS ; ++i)
Expand All @@ -112,6 +122,28 @@ unsigned int get_mmu_mapping_for(unsigned int vaddr) {
return A_BAD_ADDR;
}

unsigned char is_dtlb_mapping(unsigned int vaddr) {
unsigned int i;
vaddr = get_pfn(vaddr);

for (i = 0 ; i < MAX_MMU_SLOTS ; ++i)
if ((mappings[i].vaddr == vaddr) && (mappings[i].metadata & (MAPPING_IS_VALID)) && (mappings[i].metadata & (DTLB_MAPPING)))
return 1;

return 0;
}

unsigned char is_itlb_mapping(unsigned int vaddr) {
unsigned int i;
vaddr = get_pfn(vaddr);

for (i = 0 ; i < MAX_MMU_SLOTS ; ++i)
if ((mappings[i].vaddr == vaddr) && (mappings[i].metadata & (MAPPING_IS_VALID)) && (mappings[i].metadata & (ITLB_MAPPING)))
return 1;

return 0;
}

unsigned char remove_mmu_mapping_for(unsigned int vaddr) {
int i;
vaddr = get_pfn(vaddr);
Expand Down Expand Up @@ -195,6 +227,9 @@ unsigned int write_word_with_mmu_enabled(register unsigned int vaddr, register u

void call_function_with_itlb_enabled(void (*f)(void))
{
register unsigned int stack;
asm volatile("mv %0, sp" : "=r"(stack) :: );
printf("call stack == 0x%08x\n", stack);
asm volatile(
"xor r11, r11, r11\n\t"
"ori r11, r11, 0x10\n\t"
Expand Down
50 changes: 50 additions & 0 deletions software/mmu-bios/tlb_miss_handler.c
@@ -0,0 +1,50 @@
#include <hal/mmu.h>
#include <base/mmu.h>

void dtlb_miss_handler(void)
{
unsigned int vaddr, paddr;

// retrieve virtual address which caused the page fault
asm volatile("rcsr %0, dtlbma" : "=r"(vaddr) :: );

/*
* check if there is an existing mapping for that virtual address
* if yes: refill the DTLB with it
* if not: we panic() !
*/
paddr = get_mmu_mapping_for(vaddr);
if (paddr == A_BAD_ADDR || !is_dtlb_mapping(vaddr))
{
puts("Unrecoverable DTLB page fault !");
panic();
}

printf("Refilling DTLB with mapping 0x%08X->0x%08X\n", vaddr, paddr);
mmu_dtlb_map(vaddr, paddr);
}

void itlb_miss_handler(void)
{
unsigned int vaddr, paddr;

asm volatile("rcsr %0, itlbma" : "=r"(vaddr) :: );
printf("Address 0x%08X caused an ITLB page fault\n", vaddr);

paddr = get_mmu_mapping_for(vaddr);
if (paddr == A_BAD_ADDR)
{
puts("No such mapping !");
puts("Unrecoverable ITLB page fault !");
panic();
}

if (!is_itlb_mapping(vaddr))
{
puts("Mapping not in ITLB");
panic();
}

printf("Refilling ITLB with mapping 0x%08X->0x%08X\n", vaddr, paddr);
mmu_itlb_map(vaddr, paddr);
}

0 comments on commit 4225524

Please sign in to comment.