Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also compare across forks.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, 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
View
13 software/include/base/mmu.h
@@ -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
View
19 software/include/hal/mmu.h
@@ -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
View
2  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
+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
View
60 software/mmu-bios/dtlb_exception_handling_tests.c
@@ -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);
+
+}
View
22 software/mmu-bios/dtlb_miss_handler.c
@@ -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);
+
}
View
2  software/mmu-bios/linker.ld
@@ -4,7 +4,7 @@ ENTRY(_start)
__DYNAMIC = 0;
MEMORY {
- sram : ORIGIN = 0x44000000, LENGTH = 0x4100
+ sram : ORIGIN = 0x44000000, LENGTH = 0x7100
}
SECTIONS
View
4 software/mmu-bios/main.c
@@ -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)
{
View
139 software/mmu-bios/mmu.c
@@ -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.