Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

MMU DTLB page fault handling working on FPGA

  • Loading branch information...
commit 790d6542035bad60a5468c3cec5b69e7c4c7175e 1 parent 23f3785
Yann Sionneau authored
2  cores/lm32/rtl/lm32_cpu.v
View
@@ -2143,7 +2143,7 @@ begin
`LM32_CSR_JRX: csr_read_data_x = jrx_csr_read_data;
`endif
`LM32_CSR_CFG2: csr_read_data_x = cfg2;
- `LM32_CSR_TLB_DBG: csr_read_data_x = load_store_csr_read_data_x;
+ `LM32_CSR_TLB_VADDRESS: csr_read_data_x = load_store_csr_read_data_x;
default: csr_read_data_x = {`LM32_WORD_WIDTH{1'bx}};
endcase
73 cores/lm32/rtl/lm32_dcache.v
View
@@ -110,6 +110,7 @@ module lm32_dcache (
csr_write_enable,
exception_x,
eret_q_x,
+ exception_m,
// ----- Outputs -----
stall_request,
restart_request,
@@ -118,7 +119,7 @@ module lm32_dcache (
refilling,
load_data,
// To pipeline
- dtlb_miss_q,
+ dtlb_miss_int,
kernel_mode,
pa,
csr_read_data
@@ -138,7 +139,6 @@ parameter dtlb_sets = 1024; // Number of lines of DTLB
parameter page_size = 4096; // System page size
`define LM32_DTLB_IDX_RNG addr_dtlb_index_msb:addr_dtlb_index_lsb
-//`define LM32_DTLB_INVALID_TAG { {9{1'b1}}, `FALSE}
`define LM32_DTLB_ADDRESS_PFN_RNG addr_pfn_msb:addr_pfn_lsb
`define LM32_PAGE_OFFSET_RNG addr_page_offset_msb:addr_page_offset_lsb
`define LM32_DTLB_INVALID_ADDRESS { vpfn_width{1'b1} }
@@ -206,6 +206,7 @@ input [`LM32_CSR_RNG] csr; // CSR read/write index
input [`LM32_WORD_RNG] csr_write_data; // Data to write to specified CSR
input csr_write_enable; // CSR write enable
input exception_x; // An exception occured in the X stage
+input exception_m;
input eret_q_x;
/////////////////////////////////////////////////////
@@ -231,9 +232,7 @@ wire [`LM32_WORD_RNG] load_data;
output kernel_mode;
wire kernel_mode;
-output dtlb_miss_q;
-//output dtlb_miss;
-//output dtlb_miss_int;
+output dtlb_miss_int;
/////////////////////////////////////////////////////
// Internal nets and registers
@@ -294,8 +293,8 @@ reg [addr_dtlb_index_width-1:0] dtlb_update_set;
reg dtlb_flushing;
reg [addr_dtlb_index_width-1:0] dtlb_flush_set;
wire dtlb_miss;
-reg dtlb_miss_q = 0;
-reg dtlb_miss_int = 0;
+reg dtlb_miss_q = `FALSE;
+wire dtlb_miss_int;
reg [`LM32_WORD_RNG] dtlb_miss_addr;
wire dtlb_data_valid;
wire [`LM32_DTLB_LOOKUP_RANGE] dtlb_lookup;
@@ -465,8 +464,6 @@ end
generate
for (i = 0; i < associativity; i = i + 1)
begin : match
-// FIXME : We need to put physical address coming out from MMU instead of address_m[]
-//assign way_match[i] = ({way_tag[i], way_valid[i]} == {address_m[`LM32_DC_ADDR_TAG_RNG], `TRUE});
assign dtlb_read_tag = dtlb_read_data[`LM32_DTLB_TAG_RANGE];
assign dtlb_data_valid = dtlb_read_data[`LM32_DTLB_VALID_BIT];
@@ -474,18 +471,7 @@ assign dtlb_lookup = dtlb_read_data[`LM32_DTLB_LOOKUP_RANGE];
assign way_match[i] = (kernel_mode_reg == `LM32_KERNEL_MODE) ?
({way_tag[i], way_valid[i]} == {address_m[`LM32_DC_ADDR_TAG_RNG], `TRUE})
- : /*dtlb_data_valid && (dtlb_read_tag == address_m[`LM32_DC_ADDR_TAG_RNG]) &&
- */ ({way_tag[i], way_valid[i]} == {dtlb_lookup, `TRUE});
-
-/*always @(*)
-begin
- if (kernel_mode_reg == `LM32_KERNEL_MODE)
- way_match[i] <= ({way_tag[i], way_valid[i]} == {address_m[`LM32_DC_ADDR_TAG_RNG], `TRUE});
- else if (dtlb_read_tag == `LM32_DTLB_TAG_INVALID) // DTLB tag is invalid
- way_match[i] <= `FALSE;
- else
- way_match[i] <= ({way_tag[i], way_valid[i]} == {dtlb_read_data, `TRUE});
-end*/
+ : ({way_tag[i], way_valid[i]} == {dtlb_lookup, `TRUE});
end
endgenerate
@@ -555,13 +541,7 @@ assign dtlb_data_read_address = address_x[`LM32_DTLB_IDX_RNG];
assign dtlb_tag_read_address = address_x[`LM32_DTLB_IDX_RNG];
// tlb_update_address will receive data from a CSR register
-assign dtlb_data_write_address = /*(dtlb_flushing == `TRUE)
- ? dtlb_flush_set
- : */dtlb_update_vaddr_csr_reg[`LM32_DTLB_IDX_RNG];
-
-assign dtlb_tag_write_address = (dtlb_flushing == `TRUE)
- ? dtlb_flush_set
- : dtlb_update_vaddr_csr_reg[`LM32_DTLB_IDX_RNG];
+assign dtlb_data_write_address = dtlb_update_vaddr_csr_reg[`LM32_DTLB_IDX_RNG];
assign dtlb_data_read_port_enable = (stall_x == `FALSE) || !stall_m;
assign dtlb_write_port_enable = dtlb_updating || dtlb_flushing;
@@ -610,7 +590,7 @@ assign tmem_write_data[`LM32_DC_TAGS_VALID_RNG] = ((last_refill == `TRUE) || (va
assign tmem_write_data[`LM32_DC_TAGS_TAG_RNG] = refill_address[`LM32_DC_ADDR_TAG_RNG];
// Signals that indicate which state we are in
-assign flushing = state[0]; //|| dtlb_miss;
+assign flushing = state[0];
assign check = state[1];
assign refill = state[2];
@@ -683,8 +663,6 @@ begin
end
else if (dflush == `TRUE)
state <= `LM32_DC_STATE_FLUSH;
-// else if (dtlb_miss == `TRUE)
-// refill_address <= physical_address;
end
// Refill a cache line
@@ -718,35 +696,24 @@ begin
end
end
-assign csr_read_data = latest_store_tlb_lookup;
+assign csr_read_data = dtlb_miss_addr;
assign dtlb_miss = (kernel_mode_reg == `LM32_USER_MODE) && (load_q_m || store_q_m) && ~(dtlb_data_valid);
always @(posedge clk_i `CFG_RESET_SENSITIVITY)
begin
if (rst_i == `TRUE)
- dtlb_miss_int <= 0;
+ dtlb_miss_q <= `FALSE;
else
begin
- if (dtlb_miss)
- dtlb_miss_int <= 1;
- else
- dtlb_miss_int <= 0;
+ if (dtlb_miss && ~dtlb_miss_q)
+ dtlb_miss_q <= `TRUE;
+ else if (dtlb_miss_q && exception_m)
+ dtlb_miss_q <= `FALSE;
end
end
-always @(posedge clk_i `CFG_RESET_SENSITIVITY)
-begin
- if (rst_i == `TRUE)
- dtlb_miss_q <= 0;
- else
- begin
- if (dtlb_miss_int)
- dtlb_miss_q <= 1;
- else
- dtlb_miss_q <= 0;
- end
-end
+assign dtlb_miss_int = (dtlb_miss || dtlb_miss_q);
always @(posedge clk_i `CFG_RESET_SENSITIVITY)
begin
@@ -768,10 +735,8 @@ begin
dtlb_flushing <= 0;
if (dtlb_miss == `TRUE)
begin
-// dtlb_flushing <= 0;
-// dtlb_flush_set <= address_m[addr_dtlb_index_width-1:0];
dtlb_miss_addr <= address_m;
- $display("ERROR : DTLB MISS on addr 0x%08X at time %t", address_m, $time);
+ $display("WARNING : DTLB MISS on addr 0x%08X at time %t", address_m, $time);
end
if (csr_write_enable && csr_write_data[0])
begin
@@ -827,9 +792,9 @@ begin
kernel_mode_reg <= `LM32_KERNEL_MODE;
else
begin
- if (/*exception_x || */switch_to_kernel_mode)
+ if (exception_x || switch_to_kernel_mode)
kernel_mode_reg <= `LM32_KERNEL_MODE;
- else if (/*eret_q_x || */switch_to_user_mode)
+ else if (eret_q_x || switch_to_user_mode)
kernel_mode_reg <= `LM32_USER_MODE;
end
end
4 cores/lm32/rtl/lm32_load_store_unit.v
View
@@ -429,6 +429,7 @@ lm32_dcache #(
.csr_write_enable (csr_write_enable),
.exception_x (exception_x),
.eret_q_x (eret_q_x),
+ .exception_m (exception_m),
// ----- Outputs -----
.stall_request (dcache_stall_request),
.restart_request (dcache_restart_request),
@@ -436,8 +437,7 @@ lm32_dcache #(
.refill_address (dcache_refill_address),
.refilling (dcache_refilling),
.load_data (dcache_data_m),
-// .dtlb_miss (dtlb_miss),
- .dtlb_miss_q (dtlb_miss),
+ .dtlb_miss_int (dtlb_miss),
.kernel_mode (kernel_mode),
.pa (physical_address),
.csr_read_data (csr_read_data)
196 software/bios/dtlb_exception_handling_tests.c
View
@@ -1,160 +1,78 @@
-#include <hal/mmu.h>
-
-#define PAGE_SIZE (4096)
-
-#define MAX_MMU_SLOTS 10
-#define NO_EMPTY_SLOT (MAX_MMU_SLOTS + 1)
-
-#define A_BAD_ADDR (0)
-
-#define NULL (0)
-
-#define get_pfn(x) (x & ~(PAGE_SIZE - 1))
-
-struct mmu_mapping {
-
- unsigned int vaddr;
- unsigned int paddr;
- char valid;
-
-} mappings[10];
-
/*
- * 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
+ * Milkymist SoC (Software)
+ * Copyright (C) 2012 Yann Sionneau <yann.sionneau@gmail.com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 3 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-unsigned int mmu_map(unsigned int vaddr, unsigned int paddr) {
- int i;
- int empty_slot = NO_EMPTY_SLOT;
- vaddr = get_pfn(vaddr);
-
- for (i = 0 ; i < MAX_MMU_SLOTS ; ++i)
- {
- if (!mappings[i].valid)
- empty_slot = i;
- if (vaddr == mappings[i].vaddr && paddr == mappings[i].paddr)
- return 1;
- }
-
- if (empty_slot == NO_EMPTY_SLOT)
- return empty_slot;
-
- mappings[empty_slot].vaddr = vaddr;
- mappings[empty_slot].paddr = paddr;
- mappings[empty_slot].valid = 1;
- mmu_dtlb_map(vaddr, paddr);
-
- return 1;
-}
+#include <hal/mmu.h>
+#include <base/mmu.h>
+#include <base/stdio.h>
-unsigned int get_mmu_mapping_for(unsigned int vaddr) {
- int i;
- vaddr = get_pfn(vaddr);
+void dtlb_exception_handling_tests() {
- for (i = 0 ; i < MAX_MMU_SLOTS ; ++i)
- if (mappings[i].valid && vaddr == mappings[i].vaddr)
- return mappings[i].paddr;
+ register unsigned int stack, addr;
+ unsigned int data;
+ int ret;
- return A_BAD_ADDR;
-}
+ asm volatile("mv %0, sp" : "=r"(stack) :: );
-unsigned int invalidate_mmu_mapping(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;
-}
+ ret = mmu_map(stack, stack);
+ check_for_error(ret);
-static void panic(void) {
- puts("PANIC !");
- while(1)
- asm volatile("nop");
-}
+ ret = mmu_map(stack-0x1000, stack-0x1000);
+ check_for_error(ret);
-static void check_for_error(int ret) {
- if (ret)
- return;
+ printf("stack == 0x%08X\n", stack);
- if (ret == NO_EMPTY_SLOT) {
- puts("No empty slot in MMU mappings structure anymore");
- panic();
- }
+ addr = 0x44004004;
- if ( !ret ) {
- puts("Unknown issue");
- panic();
- }
-}
+ printf("\n=> Mapping 0x%08X to 0x%08X\n", addr, addr);
+ ret = mmu_map(addr, addr);
+ check_for_error(ret);
-void dtlb_exception_handling_tests() {
+ data = 42;
+ printf("=> Writing %d to physical address 0x%08X\n", data, addr);
+ *(unsigned int *)addr = data;
- register unsigned int stack, addr, data;
- int ret;
+ 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);
- asm volatile("mv %0, sp" : "=r"(stack) :: );
+ printf("=> Invalidating the mapping of virtual address 0x%08X in the TLB\n", addr);
+ mmu_dtlb_invalidate(addr);
- ret = mmu_map(stack, stack);
- check_for_error(ret);
+ data = 43;
+ printf("=> Writing %d to physical address 0x%08X\n", data, addr);
+ *(unsigned int *)addr = data;
- ret = mmu_map(stack-0x1000, stack-0x1000);
+ 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("stack == 0x%08X\n", stack);
+ 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;
- addr = 0x44002342; // Random address
- *(unsigned int *)addr = 42;
-// mmu_map(addr, addr);
-
- printf("Address 0x%08X mapped to itself, value : ", addr);
-
- asm volatile(
- "xor r11, r11, r11\n\t"
- "ori r11, r11, 0x11\n\t"
- "wcsr tlbctrl, r11\n\t" // this 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"
- "xor r11, r11, r11\n\t"
- "ori r11, r11, 0x9\n\t"
- "wcsr tlbctrl, r11\n\t" // this disactivates the mmu
- "xor r0, r0, r0" : "=&r"(data) : "r"(addr) : "r11"
- );
-
- printf("%d\n", data);
-
- invalidate_mmu_mapping(addr);
-
- printf("DTLB has just been invalidated, next access to 0x%08X should trigger a DTLB exception\n", addr);
-
- printf("Address 0x%08X not mapped, value : ", addr);
-
- asm volatile(
- "xor r11, r11, r11\n\t"
- "ori r11, r11, 0x11\n\t"
- "wcsr tlbctrl, r11\n\t" // this 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"
- "xor r11, r11, r11\n\t"
- "ori r11, r11, 0x9\n\t"
- "wcsr tlbctrl, r11\n\t" // this disactivates the mmu
- "xor r0, r0, r0" : "=&r"(data) : "r"(addr) : "r11"
- );
-
- printf("%d\n", 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);
}
41 software/bios/dtlb_miss_handler.c
View
@@ -1,8 +1,43 @@
+/*
+ * Milkymist SoC (Software)
+ * Copyright (C) 2012 Yann Sionneau <yann.sionneau@gmail.com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 3 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
#include <hal/mmu.h>
+#include <base/mmu.h>
+
+void dtlb_miss_handler(void)
+{
+ unsigned int vaddr, paddr;
+
+ // retrieve virtual address which caused the page fault
+ asm volatile("rcsr %0, dtlbma" : "=r"(vaddr) :: );
-void dtlb_miss_handler(void) {
+ /*
+ * 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("[TLB miss handler] Unrecoverable page fault !");
+ panic();
+ }
- disable_dtlb();
- printf("TOTO");
+ printf("[TLB miss handler] Refilling DTLB with mapping 0x%08X->0x%08X\n", vaddr, paddr);
+ mmu_dtlb_map(vaddr, paddr);
}
29 software/include/base/mmu.h
View
@@ -0,0 +1,29 @@
+/*
+ * Milkymist SoC (Software)
+ * Copyright (C) 2012 Yann Sionneau <yann.sionneau@gmail.com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 3 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#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);
+
+#endif
20 software/include/hal/mmu.h
View
@@ -15,6 +15,22 @@
* 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 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 +49,7 @@
} while(0);
void mmu_dtlb_map(unsigned int vpfn, unsigned int pfn);
+unsigned int read_word_with_mmu_enabled(unsigned int vaddr);
+void mmu_dtlb_invalidate(unsigned int vaddr);
+
+#endif
2  software/libbase/Makefile
View
@@ -1,7 +1,7 @@
MMDIR=../..
include $(MMDIR)/software/include.mak
-OBJECTS_ALL=divsi3.o libc.o crc16.o crc32.o console.o blockdev.o fatfs.o system.o board.o uart.o
+OBJECTS_ALL=divsi3.o libc.o crc16.o crc32.o console.o blockdev.o fatfs.o system.o board.o uart.o mmu.o
OBJECTS=$(OBJECTS_ALL) softfloat.o softfloat-glue.o vsnprintf.o atof.o malloc.o
OBJECTS_LIGHT=$(OBJECTS_ALL) vsnprintf-nofloat.o
116 software/libbase/mmu.c
View
@@ -0,0 +1,116 @@
+/*
+ * Milkymist SoC (Software)
+ * Copyright (C) 2012 Yann Sionneau <yann.sionneau@gmail.com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 3 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/* @vpfn : virtual page frame number
+ * @pfn : physical page frame number
+ */
+
+#include <hal/mmu.h>
+#include <base/mmu.h>
+
+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;
+ int empty_slot = NO_EMPTY_SLOT;
+ vaddr = get_pfn(vaddr);
+ paddr = get_pfn(paddr);
+
+ 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();
+ }
+}
30 software/libhal/mmu.c
View
@@ -15,6 +15,9 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+#include <hal/mmu.h>
+#include <base/mmu.h>
+
/* @vpfn : virtual page frame number
* @pfn : physical page frame number
*/
@@ -42,3 +45,30 @@ inline void mmu_dtlb_invalidate(unsigned int vaddr)
"ori r11, r11, 0x21\n\t"
"wcsr tlbctrl, r11":::"r11");
}
+
+/* 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;
+}
Please sign in to comment.
Something went wrong with that request. Please try again.