Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: fallen/milkymist-mmu
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: 033c430
Choose a base ref
...
head repository: fallen/milkymist-mmu
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 3d8f348
Choose a head ref
  • 2 commits
  • 5 files changed
  • 1 contributor

Commits on Jun 10, 2012

  1. Copy the full SHA
    0b986a8 View commit details
  2. Copy the full SHA
    3d8f348 View commit details
Showing with 98 additions and 17 deletions.
  1. +1 −1 software/include/base/mmu.h
  2. +15 −2 software/include/hal/mmu.h
  3. +4 −4 software/mmu-bios/dtlb_exception_handling_tests.c
  4. +39 −2 software/mmu-bios/main.c
  5. +39 −8 software/mmu-bios/mmu.c
2 changes: 1 addition & 1 deletion software/include/base/mmu.h
Original file line number Diff line number Diff line change
@@ -3,7 +3,7 @@

#include <hal/mmu.h>

unsigned int mmu_map(unsigned int vaddr, unsigned int paddr);
unsigned int mmu_map(unsigned int vaddr, unsigned int paddr, char metadata);
unsigned int get_mmu_mapping_for(unsigned int vaddr);
unsigned char remove_mmu_mapping_for(unsigned int vaddr);
void panic(void);
17 changes: 15 additions & 2 deletions software/include/hal/mmu.h
Original file line number Diff line number Diff line change
@@ -25,12 +25,25 @@
#define NULL (0)
#define get_pfn(x) (x & ~(PAGE_SIZE - 1))

#define ITLB_MAPPING (1)
#define DTLB_MAPPING (1 << 1)
#define MAPPING_CAN_READ (1 << 2)
#define MAPPING_CAN_WRITE (1 << 3)
#define MAPPING_COPY_ON_WRITE (1 << 4)
#define MAPPING_IS_VALID (1 << 5)

struct mmu_mapping {

unsigned int vaddr;
unsigned int paddr;
char valid;

char metadata;
// x x x x x x x x
// | | | | | |-> ITLB mapping
// | | | | |-> DTLB mapping
// | | | |-> CAN_READ
// | | |-> CAN_WRITE
// | |-> COPY_ON_WRITE: Not Implemented Yet
// |-> MAPPING_IS_VALID
};

#define enable_dtlb() do { \
8 changes: 4 additions & 4 deletions software/mmu-bios/dtlb_exception_handling_tests.c
Original file line number Diff line number Diff line change
@@ -9,18 +9,18 @@ void dtlb_exception_handling_tests() {

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

ret = mmu_map(stack, stack);
ret = mmu_map(stack, stack, DTLB_MAPPING | MAPPING_CAN_READ | MAPPING_CAN_WRITE);
check_for_error(ret);

ret = mmu_map(stack-0x1000, stack-0x1000);
ret = mmu_map(stack-0x1000, stack-0x1000, DTLB_MAPPING | MAPPING_CAN_READ | MAPPING_CAN_WRITE);
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);
ret = mmu_map(addr, addr, DTLB_MAPPING | MAPPING_CAN_READ | MAPPING_CAN_WRITE);
check_for_error(ret);

data = 42;
@@ -43,7 +43,7 @@ void dtlb_exception_handling_tests() {
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
ret = mmu_map(addr, addr+0x1000, DTLB_MAPPING | MAPPING_CAN_READ | MAPPING_CAN_WRITE); // Map to something else
check_for_error(ret);

printf("=> Invalidating the mapping of virtual address 0x%08X in the TLB\n", addr);
41 changes: 39 additions & 2 deletions software/mmu-bios/main.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#include "main.h"

#include <base/mmu.h>

void uart_write(char c)
{
@@ -72,11 +72,48 @@ int printf(const char *fmt, ...)
return len;
}

void f(void) {
CSR_UART_RXTX = '@';
asm volatile("bi f" ::: ); // We intinitely loop to f()
asm volatile("xor r0, r0, r0\n\t"
"xor r0, r0, r0" ::: );
}

void itlbtest(void) {
register unsigned int stack, f_addr;
unsigned int *p;
unsigned int *pdest;

asm volatile("mv %0, sp" : "=r"(stack) :: );
printf("stack == 0x%08X\n", stack);

printf("f() is located at 0x%p\n", f);

f_addr = 0x44004000;
printf("Mapping f() into virtual memory at 0x%08X [physical == 0x%08X]\n", f_addr, f_addr+0x1000);

mmu_map(f_addr, f_addr + 0x1000, ITLB_MAPPING | MAPPING_CAN_READ);
puts("Mapping DONE");

// We copy f's code to 0x44005000
for (p = f, pdest = 0x44005000 ; p < f + 0x1000 ; p++, pdest++)
*pdest = *p;
puts("Copy DONE");

asm volatile("wcsr DCC, r0");
asm volatile("wcsr ICC, r0");
puts("Instruction and Data caches have been invalidated");

call_function_with_itlb_enabled(f_addr);
puts("Call DONE");
}

int main(int argc, char **argv)
{
asm volatile("wcsr IE, r0");
// dtlb_load_test();
dtlb_exception_handling_tests();
// dtlb_exception_handling_tests();
itlbtest();

while (1)
{
47 changes: 39 additions & 8 deletions software/mmu-bios/mmu.c
Original file line number Diff line number Diff line change
@@ -59,7 +59,7 @@ struct mmu_mapping mappings[MAX_MMU_SLOTS];
* If there is no empty slot anymore then we fail
*/

unsigned int mmu_map(unsigned int vaddr, unsigned int paddr) {
unsigned int mmu_map(unsigned int vaddr, unsigned int paddr, char metadata) {
int i;
register unsigned int stack;
int empty_slot = NO_EMPTY_SLOT;
@@ -71,9 +71,9 @@ unsigned int mmu_map(unsigned int vaddr, unsigned int paddr) {

for (i = 0 ; i < MAX_MMU_SLOTS ; ++i)
{
if (!mappings[i].valid)
if (!(mappings[i].metadata & MAPPING_IS_VALID))
empty_slot = i;
if ((vaddr == mappings[i].vaddr) && (paddr == mappings[i].paddr) && mappings[i].valid)
if ((vaddr == mappings[i].vaddr) && (paddr == mappings[i].paddr) && (mappings[i].metadata & MAPPING_IS_VALID))
{
puts("Already mapped !");
return 1;
@@ -88,8 +88,14 @@ unsigned int mmu_map(unsigned int vaddr, unsigned int paddr) {

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

if (metadata & ITLB_MAPPING)
mmu_itlb_map(vaddr, paddr);

if (metadata & DTLB_MAPPING)
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;
@@ -100,7 +106,7 @@ unsigned int get_mmu_mapping_for(unsigned int vaddr) {
vaddr = get_pfn(vaddr);

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

return A_BAD_ADDR;
@@ -112,10 +118,10 @@ unsigned char remove_mmu_mapping_for(unsigned int vaddr) {

for (i = 0 ; i < MAX_MMU_SLOTS ; ++i)
{
if (mappings[i].valid && (vaddr == mappings[i].vaddr))
if ((mappings[i].metadata & MAPPING_IS_VALID) && (vaddr == mappings[i].vaddr))
{
mmu_dtlb_invalidate(vaddr);
mappings[i].valid = 0;
mappings[i].metadata &= ~MAPPING_IS_VALID;
return 1;
}
}
@@ -186,3 +192,28 @@ unsigned int write_word_with_mmu_enabled(register unsigned int vaddr, register u
"xor r0, r0, r0\n\t" :: "r"(vaddr), "r"(data) : "r11"
);
}

void call_function_with_itlb_enabled(void (*f)(void))
{
asm volatile(
"xor r11, r11, r11\n\t"
"ori r11, r11, 0x10\n\t"
"wcsr tlbctrl, r11\n\t" // Activates ITLB
"call %0\n\t"
"xor r11, r11, r11\n\t"
"ori r11, r11, 0x8\n\t"
"wcsr tlbctrl, r11" :: "r"(f) : "r11" // Disactivates ITLB
);
}

inline void mmu_itlb_map(unsigned int vpfn, unsigned int pfn)
{

asm volatile ("wcsr tlbvaddr, %0" :: "r"(vpfn) : );

asm volatile ("wcsr tlbpaddr, %0" :: "r"(pfn) : );

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