Skip to content
This repository
Browse code

Add BIOS support for ITLB page fault handling

  • Loading branch information...
commit 4225524cf018b905f50db00ac01f00d20544f135 1 parent 3d8f348
Yann Sionneau authored
16  software/include/hal/mmu.h
@@ -62,6 +62,22 @@ struct mmu_mapping {
62 62
 			 "xor r0, r0, r0":::"r11"); \
63 63
 } while(0);
64 64
 
  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
+
65 81
 void mmu_dtlb_map(unsigned int vpfn, unsigned int pfn);
66 82
 
67 83
 #endif
2  software/mmu-bios/Makefile
... ...
@@ -1,7 +1,7 @@
1 1
 MMDIR=../..
2 2
 include $(MMDIR)/software/include.mak
3 3
 
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
5 5
 SEGMENTS=-j .text -j .data -j .rodata
6 6
 
7 7
 all: bios.bin
9  software/mmu-bios/crt0.S
@@ -119,6 +119,15 @@ _dtlb_miss_exception_handler:
119 119
 	nop
120 120
 	nop
121 121
 
  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
+
122 131
 macaddress:
123 132
 	.byte 0x10
124 133
 	.byte 0xe2
26  software/mmu-bios/dtlb_miss_handler.c
... ...
@@ -1,26 +0,0 @@
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)
18  
-	{
19  
-		puts("Unrecoverable 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  
-}
14  software/mmu-bios/main.c
... ...
@@ -1,6 +1,8 @@
1 1
 #include "main.h"
2 2
 #include <base/mmu.h>
3 3
 
  4
+extern void call_function_with_itlb_enabled(void (*f)(void));
  5
+
4 6
 void uart_write(char c)
5 7
 {
6 8
 	unsigned int oldmask;
@@ -74,7 +76,7 @@ int printf(const char *fmt, ...)
74 76
 
75 77
 void f(void) {
76 78
 	CSR_UART_RXTX = '@';
77  
-	asm volatile("bi f" ::: ); // We intinitely loop to f()
  79
+//	asm volatile("bi f" ::: ); // We intinitely loop to f()
78 80
 	asm volatile("xor r0, r0, r0\n\t"
79 81
 		     "xor r0, r0, r0" ::: );
80 82
 }
@@ -92,9 +94,15 @@ void itlbtest(void) {
92 94
 	f_addr = 0x44004000;
93 95
 	printf("Mapping f() into virtual memory at 0x%08X [physical == 0x%08X]\n", f_addr, f_addr+0x1000);
94 96
 
  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);
95 99
 	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);
96 102
 	puts("Mapping DONE");
97 103
 
  104
+	mmu_itlb_invalidate(f_addr);
  105
+
98 106
 	// We copy f's code to 0x44005000
99 107
 	for (p = f, pdest = 0x44005000 ; p < f + 0x1000 ; p++, pdest++)
100 108
 		*pdest = *p;
@@ -105,7 +113,11 @@ void itlbtest(void) {
105 113
 	puts("Instruction and Data caches have been invalidated");
106 114
 
107 115
 	call_function_with_itlb_enabled(f_addr);
  116
+	disable_dtlb();
  117
+	disable_itlb();
108 118
 	puts("Call DONE");
  119
+	while(1)
  120
+		asm volatile("xor r0, r0, r0");
109 121
 }
110 122
 
111 123
 int main(int argc, char **argv)
37  software/mmu-bios/mmu.c
@@ -47,6 +47,16 @@ inline void mmu_dtlb_invalidate(unsigned int vaddr)
47 47
 		      "wcsr tlbctrl, r11":::"r11");
48 48
 }
49 49
 
  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
+
50 60
 struct mmu_mapping mappings[MAX_MMU_SLOTS];
51 61
 
52 62
 
@@ -102,7 +112,7 @@ unsigned int mmu_map(unsigned int vaddr, unsigned int paddr, char metadata) {
102 112
 }
103 113
 
104 114
 unsigned int get_mmu_mapping_for(unsigned int vaddr) {
105  
-	int i;
  115
+	unsigned int i;
106 116
 	vaddr = get_pfn(vaddr);
107 117
 
108 118
 	for (i = 0 ; i < MAX_MMU_SLOTS ; ++i)
@@ -112,6 +122,28 @@ unsigned int get_mmu_mapping_for(unsigned int vaddr) {
112 122
 	return A_BAD_ADDR;
113 123
 }
114 124
 
  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
+
115 147
 unsigned char remove_mmu_mapping_for(unsigned int vaddr) {
116 148
 	int i;
117 149
 	vaddr = get_pfn(vaddr);
@@ -195,6 +227,9 @@ unsigned int write_word_with_mmu_enabled(register unsigned int vaddr, register u
195 227
 
196 228
 void call_function_with_itlb_enabled(void (*f)(void))
197 229
 {
  230
+	register unsigned int stack;
  231
+	asm volatile("mv %0, sp" : "=r"(stack) :: );
  232
+	printf("call stack == 0x%08x\n", stack);
198 233
 	asm volatile(
199 234
 		"xor r11, r11, r11\n\t"
200 235
 		"ori r11, r11, 0x10\n\t"
50  software/mmu-bios/tlb_miss_handler.c
... ...
@@ -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 notes on commit 4225524

Please sign in to comment.
Something went wrong with that request. Please try again.