Skip to content

Commit 4225524

Browse files
committedJun 12, 2012
Add BIOS support for ITLB page fault handling
1 parent 3d8f348 commit 4225524

File tree

7 files changed

+125
-29
lines changed

7 files changed

+125
-29
lines changed
 

‎software/include/hal/mmu.h

+16
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,22 @@ struct mmu_mapping {
6262
"xor r0, r0, r0":::"r11"); \
6363
} while(0);
6464

65+
#define enable_itlb() do { \
66+
asm volatile ("xor r11, r11, r11\n\t" \
67+
"ori r11, r11, 0x10\n\t" \
68+
"wcsr tlbctrl, r11\n\t" \
69+
"xor r0, r0, r0":::"r11"); \
70+
} while(0);
71+
72+
#define disable_itlb() do { \
73+
asm volatile ("xor r11, r11, r11\n\t" \
74+
"ori r11, r11, 0x8\n\t" \
75+
"wcsr tlbctrl, r11\n\t" \
76+
"xor r0, r0, r0\n\t" \
77+
"xor r0, r0, r0\n\t" \
78+
"xor r0, r0, r0":::"r11"); \
79+
} while(0);
80+
6581
void mmu_dtlb_map(unsigned int vpfn, unsigned int pfn);
6682

6783
#endif

‎software/mmu-bios/Makefile

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
MMDIR=../..
22
include $(MMDIR)/software/include.mak
33

4-
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
4+
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
55
SEGMENTS=-j .text -j .data -j .rodata
66

77
all: bios.bin

‎software/mmu-bios/crt0.S

+9
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,15 @@ _dtlb_miss_exception_handler:
119119
nop
120120
nop
121121

122+
_itlb_miss_exception_handler:
123+
sw (sp+0), ra
124+
calli .save_all
125+
calli itlb_miss_handler
126+
bi .restore_all_and_eret
127+
nop
128+
nop
129+
nop
130+
122131
macaddress:
123132
.byte 0x10
124133
.byte 0xe2

‎software/mmu-bios/dtlb_miss_handler.c

-26
This file was deleted.

‎software/mmu-bios/main.c

+13-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
#include "main.h"
22
#include <base/mmu.h>
33

4+
extern void call_function_with_itlb_enabled(void (*f)(void));
5+
46
void uart_write(char c)
57
{
68
unsigned int oldmask;
@@ -74,7 +76,7 @@ int printf(const char *fmt, ...)
7476

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

97+
mmu_map(0x44003000, 0x44003000, DTLB_MAPPING | MAPPING_CAN_READ | MAPPING_CAN_WRITE);
98+
mmu_map(stack, stack, DTLB_MAPPING | MAPPING_CAN_READ | MAPPING_CAN_WRITE);
9599
mmu_map(f_addr, f_addr + 0x1000, ITLB_MAPPING | MAPPING_CAN_READ);
100+
mmu_map(itlbtest, itlbtest, ITLB_MAPPING | MAPPING_CAN_READ);
101+
mmu_map(call_function_with_itlb_enabled, call_function_with_itlb_enabled, ITLB_MAPPING | MAPPING_CAN_READ);
96102
puts("Mapping DONE");
97103

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

107115
call_function_with_itlb_enabled(f_addr);
116+
disable_dtlb();
117+
disable_itlb();
108118
puts("Call DONE");
119+
while(1)
120+
asm volatile("xor r0, r0, r0");
109121
}
110122

111123
int main(int argc, char **argv)

‎software/mmu-bios/mmu.c

+36-1
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,16 @@ inline void mmu_dtlb_invalidate(unsigned int vaddr)
4747
"wcsr tlbctrl, r11":::"r11");
4848
}
4949

50+
inline void mmu_itlb_invalidate(unsigned int vaddr)
51+
{
52+
asm volatile ("ori %0, %0, 0\n\t"
53+
"wcsr tlbvaddr, %0"::"r"(vaddr):);
54+
55+
asm volatile ("xor r11, r11, r11\n\t"
56+
"ori r11, r11, 0x20\n\t"
57+
"wcsr tlbctrl, r11":::"r11");
58+
}
59+
5060
struct mmu_mapping mappings[MAX_MMU_SLOTS];
5161

5262

@@ -102,7 +112,7 @@ unsigned int mmu_map(unsigned int vaddr, unsigned int paddr, char metadata) {
102112
}
103113

104114
unsigned int get_mmu_mapping_for(unsigned int vaddr) {
105-
int i;
115+
unsigned int i;
106116
vaddr = get_pfn(vaddr);
107117

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

125+
unsigned char is_dtlb_mapping(unsigned int vaddr) {
126+
unsigned int i;
127+
vaddr = get_pfn(vaddr);
128+
129+
for (i = 0 ; i < MAX_MMU_SLOTS ; ++i)
130+
if ((mappings[i].vaddr == vaddr) && (mappings[i].metadata & (MAPPING_IS_VALID)) && (mappings[i].metadata & (DTLB_MAPPING)))
131+
return 1;
132+
133+
return 0;
134+
}
135+
136+
unsigned char is_itlb_mapping(unsigned int vaddr) {
137+
unsigned int i;
138+
vaddr = get_pfn(vaddr);
139+
140+
for (i = 0 ; i < MAX_MMU_SLOTS ; ++i)
141+
if ((mappings[i].vaddr == vaddr) && (mappings[i].metadata & (MAPPING_IS_VALID)) && (mappings[i].metadata & (ITLB_MAPPING)))
142+
return 1;
143+
144+
return 0;
145+
}
146+
115147
unsigned char remove_mmu_mapping_for(unsigned int vaddr) {
116148
int i;
117149
vaddr = get_pfn(vaddr);
@@ -195,6 +227,9 @@ unsigned int write_word_with_mmu_enabled(register unsigned int vaddr, register u
195227

196228
void call_function_with_itlb_enabled(void (*f)(void))
197229
{
230+
register unsigned int stack;
231+
asm volatile("mv %0, sp" : "=r"(stack) :: );
232+
printf("call stack == 0x%08x\n", stack);
198233
asm volatile(
199234
"xor r11, r11, r11\n\t"
200235
"ori r11, r11, 0x10\n\t"

‎software/mmu-bios/tlb_miss_handler.c

+50
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
#include <hal/mmu.h>
2+
#include <base/mmu.h>
3+
4+
void dtlb_miss_handler(void)
5+
{
6+
unsigned int vaddr, paddr;
7+
8+
// retrieve virtual address which caused the page fault
9+
asm volatile("rcsr %0, dtlbma" : "=r"(vaddr) :: );
10+
11+
/*
12+
* check if there is an existing mapping for that virtual address
13+
* if yes: refill the DTLB with it
14+
* if not: we panic() !
15+
*/
16+
paddr = get_mmu_mapping_for(vaddr);
17+
if (paddr == A_BAD_ADDR || !is_dtlb_mapping(vaddr))
18+
{
19+
puts("Unrecoverable DTLB page fault !");
20+
panic();
21+
}
22+
23+
printf("Refilling DTLB with mapping 0x%08X->0x%08X\n", vaddr, paddr);
24+
mmu_dtlb_map(vaddr, paddr);
25+
}
26+
27+
void itlb_miss_handler(void)
28+
{
29+
unsigned int vaddr, paddr;
30+
31+
asm volatile("rcsr %0, itlbma" : "=r"(vaddr) :: );
32+
printf("Address 0x%08X caused an ITLB page fault\n", vaddr);
33+
34+
paddr = get_mmu_mapping_for(vaddr);
35+
if (paddr == A_BAD_ADDR)
36+
{
37+
puts("No such mapping !");
38+
puts("Unrecoverable ITLB page fault !");
39+
panic();
40+
}
41+
42+
if (!is_itlb_mapping(vaddr))
43+
{
44+
puts("Mapping not in ITLB");
45+
panic();
46+
}
47+
48+
printf("Refilling ITLB with mapping 0x%08X->0x%08X\n", vaddr, paddr);
49+
mmu_itlb_map(vaddr, paddr);
50+
}

0 commit comments

Comments
 (0)
Please sign in to comment.