Skip to content

Commit

Permalink
Add a test for DTLB exception handling in Milkymist BIOS
Browse files Browse the repository at this point in the history
fallen committed May 30, 2012

Verified

This commit was signed with the committer’s verified signature.
skmcgrail Sean McGrail
1 parent 43f6245 commit 23f3785
Showing 6 changed files with 202 additions and 2 deletions.
2 changes: 1 addition & 1 deletion software/bios/Makefile
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
MMDIR=../..
include $(MMDIR)/software/include.mak

OBJECTS=crt0.o isr.o main.o unlzma.o boot.o boot-helper.o splash.o dtlb_load_test.o
OBJECTS=crt0.o isr.o main.o unlzma.o boot.o boot-helper.o splash.o dtlb_load_test.o dtlb_exception_handling_tests.o dtlb_miss_handler.o
SEGMENTS=-j .text -j .data -j .rodata
LIBS=$(MMDIR)/software/libhpdmc/libhpdmc.a $(MMDIR)/software/libbase/libbase-light.a \
$(MMDIR)/software/libhal/libhal.a $(MMDIR)/software/libnet/libnet.a
20 changes: 20 additions & 0 deletions software/bios/crt0.S
Original file line number Diff line number Diff line change
@@ -97,6 +97,26 @@ _interrupt_handler:
nop
nop

_scall_handler:
bi _scall_handler
nop
nop
nop
nop
nop
nop
nop

_dtlb_miss_exception_handler:
sw (sp+0), ra
addi ea, ea, -4
calli .save_all
calli dtlb_miss_handler
bi .restore_all_and_eret
nop
nop
nop

macaddress:
.byte 0x10
.byte 0xe2
160 changes: 160 additions & 0 deletions software/bios/dtlb_exception_handling_tests.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
#include <hal/mmu.h>

#define PAGE_SIZE (4096)

#define MAX_MMU_SLOTS 10
#define NO_EMPTY_SLOT (MAX_MMU_SLOTS + 1)

#define A_BAD_ADDR (0)

#define NULL (0)

#define get_pfn(x) (x & ~(PAGE_SIZE - 1))

struct mmu_mapping {

unsigned int vaddr;
unsigned int paddr;
char valid;

} mappings[10];

/*
* This records in a global structure all MMU mappings
* If such a mapping already exists the function returns immediately.
* If such a mapping does not exist yet, vaddr is mapped to paddr and
* the mapping is recorded in the mappings[] global structure array in
* an empty slot.
* If there is no empty slot anymore then we fail
*/

unsigned int mmu_map(unsigned int vaddr, unsigned int paddr) {
int i;
int empty_slot = NO_EMPTY_SLOT;
vaddr = get_pfn(vaddr);

for (i = 0 ; i < MAX_MMU_SLOTS ; ++i)
{
if (!mappings[i].valid)
empty_slot = i;
if (vaddr == mappings[i].vaddr && paddr == mappings[i].paddr)
return 1;
}

if (empty_slot == NO_EMPTY_SLOT)
return empty_slot;

mappings[empty_slot].vaddr = vaddr;
mappings[empty_slot].paddr = paddr;
mappings[empty_slot].valid = 1;
mmu_dtlb_map(vaddr, paddr);

return 1;
}

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

for (i = 0 ; i < MAX_MMU_SLOTS ; ++i)
if (mappings[i].valid && vaddr == mappings[i].vaddr)
return mappings[i].paddr;

return A_BAD_ADDR;
}

unsigned int invalidate_mmu_mapping(unsigned int vaddr) {
int i;
vaddr = get_pfn(vaddr);
for (i = 0 ; i < MAX_MMU_SLOTS ; ++i)
{
if (mappings[i].valid && vaddr == mappings[i].vaddr) {
mmu_dtlb_invalidate(vaddr);
mappings[i].valid = 0;
return 1;
}
}
return 0;
}

static void panic(void) {
puts("PANIC !");
while(1)
asm volatile("nop");
}

static void check_for_error(int ret) {
if (ret)
return;

if (ret == NO_EMPTY_SLOT) {
puts("No empty slot in MMU mappings structure anymore");
panic();
}

if ( !ret ) {
puts("Unknown issue");
panic();
}
}

void dtlb_exception_handling_tests() {

register unsigned int stack, addr, data;
int ret;

asm volatile("mv %0, sp" : "=r"(stack) :: );

ret = mmu_map(stack, stack);
check_for_error(ret);

ret = mmu_map(stack-0x1000, stack-0x1000);
check_for_error(ret);

printf("stack == 0x%08X\n", stack);

addr = 0x44002342; // Random address
*(unsigned int *)addr = 42;
// mmu_map(addr, addr);

printf("Address 0x%08X mapped to itself, value : ", addr);

asm volatile(
"xor r11, r11, r11\n\t"
"ori r11, r11, 0x11\n\t"
"wcsr tlbctrl, r11\n\t" // this activates the mmu
"xor r0, r0, r0\n\t"
"xor r11, r11, r11\n\t"
"or r11, r11, %1\n\t"
"lw %0, (r11+0)\n\t"
"xor r11, r11, r11\n\t"
"ori r11, r11, 0x9\n\t"
"wcsr tlbctrl, r11\n\t" // this disactivates the mmu
"xor r0, r0, r0" : "=&r"(data) : "r"(addr) : "r11"
);

printf("%d\n", data);

invalidate_mmu_mapping(addr);

printf("DTLB has just been invalidated, next access to 0x%08X should trigger a DTLB exception\n", addr);

printf("Address 0x%08X not mapped, value : ", addr);

asm volatile(
"xor r11, r11, r11\n\t"
"ori r11, r11, 0x11\n\t"
"wcsr tlbctrl, r11\n\t" // this activates the mmu
"xor r0, r0, r0\n\t"
"xor r11, r11, r11\n\t"
"or r11, r11, %1\n\t"
"lw %0, (r11+0)\n\t"
"xor r11, r11, r11\n\t"
"ori r11, r11, 0x9\n\t"
"wcsr tlbctrl, r11\n\t" // this disactivates the mmu
"xor r0, r0, r0" : "=&r"(data) : "r"(addr) : "r11"
);

printf("%d\n", data);

}
8 changes: 8 additions & 0 deletions software/bios/dtlb_miss_handler.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
#include <hal/mmu.h>

void dtlb_miss_handler(void) {

disable_dtlb();
printf("TOTO");

}
4 changes: 3 additions & 1 deletion software/bios/main.c
Original file line number Diff line number Diff line change
@@ -422,7 +422,8 @@ static void help()
puts("version - display version");
puts("reboot - system reset");
puts("reconf - reload FPGA configuration");
puts("dtlbtest - runs DTLB MMU test");
puts("dtlbtest - runs DTLB MMU load store tests");
puts("detest - runs DTLB MMU exception handling tests");
}

static char *get_token(char **str)
@@ -538,6 +539,7 @@ static void do_command(char *c)
else if(strcmp(token, "rcsr") == 0) rcsr(get_token(&c));
else if(strcmp(token, "wcsr") == 0) wcsr(get_token(&c), get_token(&c));
else if(strcmp(token, "dtlbtest") == 0) dtlbtest();
else if(strcmp(token, "detest") == 0) dtlb_exception_handling_tests();

else if(strcmp(token, "") != 0)
printf("Command not found\n");
10 changes: 10 additions & 0 deletions software/libhal/mmu.c
Original file line number Diff line number Diff line change
@@ -32,3 +32,13 @@ inline void mmu_dtlb_map(unsigned int vpfn, unsigned int pfn)
"wcsr tlbctrl, r11":::"r11");

}

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

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

0 comments on commit 23f3785

Please sign in to comment.