Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

We’re showing branches in this repository, but you can also compare across forks.

base fork: fallen/milkymist-mmu
base: c8308d8
...
head fork: fallen/milkymist-mmu
compare: 795cb9d
  • 5 commits
  • 8 files changed
  • 0 commit comments
  • 1 contributor
13 software/include/base/mmu.h
View
@@ -0,0 +1,13 @@
+#ifndef __BASE_MMU_H__
+#define __BASE_MMU_H__
+
+#include <hal/mmu.h>
+
+unsigned int mmu_map(unsigned int vaddr, unsigned int paddr);
+unsigned int get_mmu_mapping_for(unsigned int vaddr);
+unsigned char remove_mmu_mapping_for(unsigned int vaddr);
+void panic(void);
+void check_for_error(int ret);
+unsigned int read_word_with_mmu_enabled(unsigned int vaddr);
+
+#endif
19 software/include/hal/mmu.h
View
@@ -15,6 +15,23 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+#ifndef __MMU_H__
+#define __MMU_H__
+
+#define PAGE_SIZE (4096)
+#define MAX_MMU_SLOTS 10
+#define NO_EMPTY_SLOT (MAX_MMU_SLOTS + 1)
+#define A_BAD_ADDR 0xffffffff
+#define NULL (0)
+#define get_pfn(x) (x & ~(PAGE_SIZE - 1))
+
+struct mmu_mapping {
+
+ unsigned int vaddr;
+ unsigned int paddr;
+ char valid;
+
+};
#define enable_dtlb() do { \
asm volatile ("xor r11, r11, r11\n\t" \
@@ -33,3 +50,5 @@
} while(0);
void mmu_dtlb_map(unsigned int vpfn, unsigned int pfn);
+
+#endif
2  software/mmu-bios/Makefile
View
@@ -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
+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
SEGMENTS=-j .text -j .data -j .rodata
all: bios.bin
60 software/mmu-bios/dtlb_exception_handling_tests.c
View
@@ -0,0 +1,60 @@
+#include <hal/mmu.h>
+#include <base/mmu.h>
+
+void dtlb_exception_handling_tests() {
+
+ register unsigned int stack, addr;
+ unsigned int 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 = 0x44004004;
+
+ printf("\n=> Mapping 0x%08X to 0x%08X\n", addr, addr);
+ ret = mmu_map(addr, addr);
+ check_for_error(ret);
+
+ data = 42;
+ printf("=> Writing %d to physical address 0x%08X\n", data, addr);
+ *(unsigned int *)addr = data;
+
+ printf("=> Activating the MMU and reading form virtual address 0x%08X\n", addr);
+ data = read_word_with_mmu_enabled(addr);
+ printf("\n<= Reading %d from virtual address 0x%08X\n\n", data, addr);
+
+ printf("=> Invalidating the mapping of virtual address 0x%08X in the TLB\n", addr);
+ mmu_dtlb_invalidate(addr);
+
+ data = 43;
+ printf("=> Writing %d to physical address 0x%08X\n", data, addr);
+ *(unsigned int *)addr = data;
+
+ printf("=> Activating the MMU and reading form virtual address 0x%08X\n", addr);
+ data = read_word_with_mmu_enabled(addr);
+ printf("\n<= Reading %d from virtual address 0x%08X\n\n", data, addr);
+
+ printf("=> Mapping 0x%08X to 0%08X\n", addr, addr+0x1000);
+ ret = mmu_map(addr, addr+0x1000); // Map to something else
+ check_for_error(ret);
+
+ printf("=> Invalidating the mapping of virtual address 0x%08X in the TLB\n", addr);
+ mmu_dtlb_invalidate(addr); // AND invalidate the mapping
+
+ data = 44;
+ printf("=> Writting %d to physical address 0x%08X\n", data, addr+0x1000);
+ *(unsigned int *)(addr + 0x1000) = data;
+
+ printf("=> Activating the MMU and reading form virtual address 0x%08X\n", addr);
+ data = read_word_with_mmu_enabled(addr);
+ printf("\n<= Reading %d from virtual address 0x%08X\n\n", data, addr);
+
+}
22 software/mmu-bios/dtlb_miss_handler.c
View
@@ -1,6 +1,26 @@
#include <hal/mmu.h>
+#include <base/mmu.h>
void dtlb_miss_handler(void)
{
- mmu_dtlb_map(0x44000000, 0x44003000);
+ 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)
+ {
+ puts("Unrecoverable page fault !");
+ panic();
+ }
+
+ printf("Refilling DTLB with mapping 0x%08X->0x%08X\n", vaddr, paddr);
+ mmu_dtlb_map(vaddr, paddr);
+
}
2  software/mmu-bios/linker.ld
View
@@ -4,7 +4,7 @@ ENTRY(_start)
__DYNAMIC = 0;
MEMORY {
- sram : ORIGIN = 0x44000000, LENGTH = 0x4100
+ sram : ORIGIN = 0x44000000, LENGTH = 0x7100
}
SECTIONS
4 software/mmu-bios/main.c
View
@@ -75,8 +75,8 @@ int printf(const char *fmt, ...)
int main(int argc, char **argv)
{
asm volatile("wcsr IE, r0");
-// asm volatile("scall");
- dtlb_load_test();
+// dtlb_load_test();
+ dtlb_exception_handling_tests();
while (1)
{
139 software/mmu-bios/mmu.c
View
@@ -18,6 +18,10 @@
/* @vpfn : virtual page frame number
* @pfn : physical page frame number
*/
+
+#include <hal/mmu.h>
+#include <base/mmu.h>
+
inline void mmu_dtlb_map(unsigned int vpfn, unsigned int pfn)
{
@@ -32,3 +36,138 @@ 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");
+}
+
+struct mmu_mapping mappings[MAX_MMU_SLOTS];
+
+
+/*
+ * 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;
+ register unsigned int stack;
+ int empty_slot = NO_EMPTY_SLOT;
+ vaddr = get_pfn(vaddr);
+ paddr = get_pfn(paddr);
+
+ asm volatile("mv %0, sp" : "=r"(stack) :: );
+ printf("stack == 0x%08X\n", stack);
+
+ for (i = 0 ; i < MAX_MMU_SLOTS ; ++i)
+ {
+ if (!mappings[i].valid)
+ empty_slot = i;
+ if ((vaddr == mappings[i].vaddr) && (paddr == mappings[i].paddr) && mappings[i].valid)
+ {
+ puts("Already mapped !");
+ return 1;
+ }
+ }
+
+ if (empty_slot == NO_EMPTY_SLOT)
+ {
+ puts("No more slots !");
+ return empty_slot;
+ }
+
+ mappings[empty_slot].vaddr = vaddr;
+ mappings[empty_slot].paddr = paddr;
+ mappings[empty_slot].valid = 1;
+ mmu_dtlb_map(vaddr, paddr);
+ printf("mapping 0x%08X->0x%08X in slot %d [0x%p]\n", vaddr, paddr, empty_slot, &mappings[empty_slot]);
+
+ 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 char remove_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))
+ {
+ mmu_dtlb_invalidate(vaddr);
+ mappings[i].valid = 0;
+ return 1;
+ }
+ }
+ return 0;
+}
+
+void panic(void) {
+ puts("PANIC !");
+ while(1)
+ asm volatile("nop");
+}
+
+void check_for_error(int ret) {
+ if (ret == 1)
+ return;
+
+ if (ret == NO_EMPTY_SLOT)
+ {
+ puts("No empty slot in MMU mappings structure anymore");
+ panic();
+ }
+
+ if ( !ret )
+ {
+ puts("Unknown issue");
+ panic();
+ }
+}
+
+/* This function activates the MMU
+ * then reads from virtual address "vaddr"
+ * and store the result in temporary variable "data".
+ * Then MMU is disactivated and the content of "data"
+ * is returned.
+ */
+
+unsigned int read_word_with_mmu_enabled(unsigned int vaddr)
+{
+ register unsigned int data;
+ asm volatile(
+ "xor r11, r11, r11\n\t"
+ "ori r11, r11, 0x11\n\t"
+ "wcsr tlbctrl, r11\n\t" // 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" // Reads from virtual address "addr"
+ "xor r11, r11, r11\n\t"
+ "ori r11, r11, 0x9\n\t"
+ "wcsr tlbctrl, r11\n\t" // Disactivates the MMU
+ "xor r0, r0, r0\n\t" : "=&r"(data) : "r"(vaddr) : "r11"
+ );
+
+ return data;
+}

No commit comments for this range

Something went wrong with that request. Please try again.