URL
https://opencores.org/ocsvn/openrisc/openrisc/trunk
Subversion Repositories openrisc
[/] [openrisc/] [trunk/] [orpsocv2/] [sw/] [tests/] [or1200/] [board/] [or1200-rfemmu.S] - Rev 535
Compare with Previous | Blame | View Log
/*Test of return from execption and MMU behaviorFor now, just a simple test confirming that the instructions we l.rfeto are executed OK.In this test we are checking that execution of instructions afterl.rfe enabling the MMU occurs OK.Mainly this is to test what happens when the first virtual addressafter a l.rfe is a cache "hit" - ensuring this instruction is notexecuted.Test method:Relocate a simple looping function to an unused page in memory, atoffset 0xf00 within that page. Translate virtual page 0 to this pageand execute it, with timer interrupts occuring, ensuring the l.rfe isbeing called regularly.Whenever the function in virtual space is so be resumed, code at theaddress matching the virtual space is executed before the l.rfe,ensuring it is in cache. If any of these instructions in the physicaladdress are executed, then the code running in virtual space willdetect this and crash.In this instance, the test function is only about 30 instructionslong. It is mapped to virtual address 0xf00. The physical address0xf00 has the same number of instructions, setting r31 to -1 (0xfffffff)This string of 32 instructions is executed before any l.rfe back to thefunction running with MMUs on in the virtual page address. The lastinstruction before the l.rfe clears r31, so if any of the instructionsin the physical address space get executed, r31 will return to0xffffffff and this can be detected by the code.The test finishes when the test function, running in virtual addressspace, has incremented a value in memory beyond the alue defined byTEST_LOOPS.The test has the possibility of being restarted and run withcaches enabled.Julius Baxter, ORSoC AB, julius.baxter@orsoc.se*/////////////////////////////////////////////////////////////////////////// //////// Copyright (C) 2010 Authors and OPENCORES.ORG //////// //////// This source file may be used and distributed without //////// restriction provided that this copyright statement is not //////// removed from the file and that any derivative work contains //////// the original copyright notice and the associated disclaimer. //////// //////// This source file is free software; you can redistribute it //////// and/or modify it under the terms of the GNU Lesser General //////// Public License as published by the Free Software Foundation; //////// either version 2.1 of the License, or (at your option) any //////// later version. //////// //////// This source 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 Lesser General Public License for more //////// details. //////// //////// You should have received a copy of the GNU Lesser General //////// Public License along with this source; if not, download it //////// from http://www.opencores.org/lgpl.shtml //////// //////////////////////////////////////////////////////////////////////////#include "spr-defs.h"#include "board.h"#include "or1200-defines.h"#define ONCE_THROUGH_WITH_CACHE_ENABLED 1#define TEST_LOOPS 0xffff#define PAGE_ADR_SHIFT 13// Should be at least 0x1000#define PAGE_OFFSET_FOR_TEST 0xf00#define TIMER_CYCLES_RATE 1000#define LOAD_SYMBOL_2_GPR(gpr,symbol) \l.movhi gpr, hi(symbol) ; \l.ori gpr, gpr, lo(symbol)/* =================================================== [ exceptions ] === */.section .vectors, "ax"/* ---[ 0x100: RESET exception ]----------------------------------------- */.org 0x100l.movhi r0, 0/* Clear status register */l.ori r1, r0, SPR_SR_SMl.mtspr r0, r1, SPR_SR/* Clear timer */l.mtspr r0, r0, SPR_TTMR/* Jump to program initialisation code */.global _startl.movhi r4, hi(_start)l.ori r4, r4, lo(_start)l.jr r4l.nop/* ---[ 0x400: itlb fault ]--------------------------------------------- */.org 0x400l.ori r3,r0,0xa00l.nop 0x2l.movhi r3,0xbaaal.ori r3,r3,0xaaadl.nop 0x2l.nop 0x1 /* We should never have a itlb miss *//* ---[ 0x500: timer exception ]---------------------------------------- */.org 0x500/* check test loop counter to see if test is over */LOAD_SYMBOL_2_GPR(r3,function_global)l.lwz r3,0(r3)l.sfgeui r3,TEST_LOOPSl.bf check_for_restartl.nop/* Write to TTMR again to clear TTMR[IP] bit */l.jal timer_loadl.nopl.j call_rfe /* continue execution */l.nop.org 0x600l.j faill.nop.org 0x700l.j faill.nop.org 0x800l.j faill.nop/* ---[ 0xa00: itlb miss ]---------------------------------------------- */.org 0xa00l.ori r3,r0,0xa00l.nop 0x2l.movhi r3,0xbaaal.ori r3,r3,0xaaadl.nop 0x2l.j 0l.nop 0x1 /* We should never have a itlb miss *//* ---[ 0xc00: system call ]-------------------------------------------- */.org 0xc00l.movhi r3,0xbaaal.ori r3,r3,0xaaadl.nop 0x2 /* Simulation report */l.j 0 /* Loop here */l.nop 0x1 /* End simulation *//* ---[ 0xE00: TRAP exception ]----------------------------------------- */.org 0xe00l.j 0l.nop 0x1/* ---[ reserved space ]------------------------------------ */.org PAGE_OFFSET_FOR_TESTcall_rfe:l.addi r31,r0,-1l.addi r31,r0,-1l.addi r31,r0,-1l.addi r31,r0,-1l.addi r31,r0,-1l.addi r31,r0,-1l.addi r31,r0,-1l.addi r31,r0,-1l.addi r31,r0,-1l.addi r31,r0,-1l.addi r31,r0,-1l.addi r31,r0,-1l.addi r31,r0,-1l.addi r31,r0,-1l.addi r31,r0,-1l.addi r31,r0,-1l.addi r31,r0,-1l.addi r31,r0,-1l.addi r31,r0,-1l.addi r31,r0,-1l.addi r31,r0,-1l.addi r31,r0,-1l.addi r31,r0,-1l.addi r31,r0,-1l.addi r31,r0,-1l.addi r31,r0,-1l.addi r31,r0,-1l.addi r31,r0,-1l.addi r31,r0,-1l.movhi r31,0l.rfe/* =================================================== [ text ] === */.section .dataimmu_sets:.long -1immu_ways:.long -1dmmu_sets:.long -1dmmu_ways:.long -1test_page_num:.long -1function_global:.long 0/* =================================================== [ text ] === */.section .text/* =================================================== [ start ] === */.global _start_start:#if ONCE_THROUGH_WITH_CACHE_ENABLED==1l.jal _cache_initl.nop#endif// Kick off testl.jal _mainl.nop/* =================================================== [ main ] === */.global _main_main:// Get MMU configurationl.jal immu_get_configl.nopl.jal dmmu_get_configl.nop// Clear IMMUl.jal immu_clearl.nop// Clear DMMUl.jal dmmu_clearl.nop// Set up stack pointer, but kind of don't need itLOAD_SYMBOL_2_GPR(r1,_stack)// What is next page above stack?l.srli r4,r1,PAGE_ADR_SHIFTl.addi r4,r4,1 /* Next page past */LOAD_SYMBOL_2_GPR(r5,test_page_num)l.sw 0(r5),r4 /* We will do tests with code in this PPN */LOAD_SYMBOL_2_GPR(r2,test_function)LOAD_SYMBOL_2_GPR(r3,test_function_end)/* Convert physical page number back to physical address */l.slli r4,r4,PAGE_ADR_SHIFT/* r4 has physical address of where we'll relocate our test program tobut we want it at an offset of PAGE_OFFSET_FOR_TEST inside that page.*/l.addi r4,r4,PAGE_OFFSET_FOR_TESTprogram_relocate_loop:l.lwz r5,0(r2)l.sw 0(r4),r5l.sfeq r2,r3l.mtspr r0,r4,SPR_DCBIR /* flush dcache */l.addi r4,r4,4 /* increment dest ptr */l.bnf program_relocate_loopl.addi r2,r2,4 /* increment src ptr */mmu_setup:/* Program relocated, setup MMU mappings *//* Physical page number of test-code is in test_page_num. We needto set up a mapping for this page in the MMU, then launch executionof it.*/LOAD_SYMBOL_2_GPR(r5,test_page_num)l.lwz r5,0(r5)/* Basically should be match-PPN of 0 translates to pagenumber test_page_num.Set up entry 0, then, and have translate address to test_page_num*/// Match registerl.ori r3,r0,SPR_ITLBMR_V /* Just this */l.mtspr r0,r3,SPR_ITLBMR_BASE(0)// Setup TR page numberl.slli r3,r5,PAGE_ADR_SHIFT //r5 = page number of target pagel.ori r3,r3,ITLB_PR_NOLIMITl.mtspr r0,r3,SPR_ITLBTR_BASE(0)timer_setup:/* Init timer to fire at rate of TIMER_CYCLES_RATE */l.jal timer_loadl.nopsr_setup:// Start test - set up EPCR to jump to PAGE_OFFSET_FOR_TESTl.ori r3,r0,PAGE_OFFSET_FOR_TESTl.mtspr r0,r3,SPR_EPCR_BASEl.mfspr r3,r0,SPR_SRl.ori r3,r3,(SPR_SR_IME|SPR_SR_TEE) /* IMMU, tick timer enable */l.mtspr r0,r3,SPR_ESR_BASE// Ensure global counter variable is zeroLOAD_SYMBOL_2_GPR(r3,function_global)l.sw 0(r3),r0// Call function entry point, check bug doesn't occurl.j call_rfel.nop// Should never get here - test is detected as finished from the// timer interrupt.check_for_restart:l.mfspr r4,r0,SPR_SRl.andi r4,r4,SPR_SR_ICE /* is instruction cache enabled? */l.sfgtu r4,r0l.bnf restart_with_cachesl.nopfinish:l.movhi r3,0x8000l.ori r3,r3,0x000dl.nop 0x2l.j 0l.nop 0x1fail:l.movhi r3,0xbaaal.ori r3,r3,0xaaadl.nop 0x2l.j 0l.nop 0x1/* A stilly test function - doing some loads/stores, and somebranchesonly touches r13 and r14*//* Should be relocatable */test_function:// Check for error - r31 should be 0l.sfne r31,r0l.bf test_function_failLOAD_SYMBOL_2_GPR(r13,function_global)l.lwz r14,0(r13) /* Load value of global */l.addi r14,r14,1l.sw 0(r13),r14 /* Store it back */l.mtspr r0,r13,SPR_DCBIR /* flush dcache *//* Every 8, branch away and back */l.andi r14,r14,0xfl.sfeq r14,r0l.bf test_function_subl.nopl.j test_functionl.noptest_function_sub:l.j test_functionl.noptest_function_fail:l.sys 0 /* Bail out with syscall */test_function_end:l.nop 0x1restart_with_caches:l.jal _cache_initl.nopl.movhi r4, hi(_start)l.ori r4, r4, lo(_start)l.jr r4l.nop/* MMU configuration functions */immu_get_config:l.mfspr r3,r0,SPR_IMMUCFGR// Number of waysl.andi r4,r3,SPR_IMMUCFGR_NTWl.addi r4,r4,1// Store the ways in immu_waysl.movhi r5,hi(immu_ways)l.ori r5,r5,lo(immu_ways)l.sw 0(r5),r4// Number of setsl.andi r4,r3,SPR_IMMUCFGR_NTSl.srli r4,r4,SPR_IMMUCFGR_NTS_OFFl.ori r6,r0,1l.sll r4,r6,r4// Store the ways in immu_waysl.movhi r5,hi(immu_sets)l.ori r5,r5,lo(immu_sets)l.jr r9 // Returnl.sw 0(r5),r4dmmu_get_config:l.mfspr r3,r0,SPR_DMMUCFGR// Number of waysl.andi r4,r3,SPR_DMMUCFGR_NTWl.addi r4,r4,1// Store the ways in dmmu_waysl.movhi r5,hi(dmmu_ways)l.ori r5,r5,lo(dmmu_ways)l.sw 0(r5),r4// Number of setsl.andi r4,r3,SPR_DMMUCFGR_NTSl.srli r4,r4,SPR_DMMUCFGR_NTS_OFFl.ori r6,r0,1l.sll r4,r6,r4// Store the ways in dmmu_waysl.movhi r5,hi(dmmu_sets)l.ori r5,r5,lo(dmmu_sets)l.jr r9 // Returnl.sw 0(r5),r4immu_clear:// r3 - immu_ways// r4 - immu_sets// r5 - work// r6 - ways counter// r7 - sets counter// r10 - match regs spr address// r11 - translate regs spr address/* Clear all IMMU match/translate register pairs */l.movhi r5,hi(immu_ways)l.ori r5,r5,lo(immu_ways)l.lwz r3,0(r5)l.movhi r5,hi(immu_sets)l.ori r5,r5,lo(immu_sets)l.lwz r4,0(r5)l.movhi r6, 0 // Clear ways countersimmu_clear_set:l.movhi r7, 0 // Clear sets counter// Calculate base of IMMU match & translate registersl.ori r10,r0,SPR_ITLBMR_BASE(0)l.ori r11,r0,SPR_ITLBTR_BASE(0)l.slli r5,r6,8 /* Multiply ways by 256 (ways<<8) */l.add r10,r10,r5l.add r11,r11,r5immu_clear_set_loop:l.mtspr r10,r0,0 /* ITLBMR_BASE(way) + set = 0 */l.mtspr r11,r0,0 /* ITLBTR_BASE(way) + set = 0 */l.addi r7,r7,1l.sfne r4,r7l.addi r10,r10,1l.bf immu_clear_set_loopl.addi r11,r11,1l.addi r6,r6,1 /* Increment ways counter */l.sfne r3,r6 /* Cleared all ways? */l.bf immu_clear_setl.nop/* Finished */l.jr r9l.nopdmmu_clear:// r3 - dmmu_ways// r4 - dmmu_sets// r5 - work// r6 - ways counter// r7 - sets counter// r10 - match regs spr address// r11 - translate regs spr address/* Clear all DMMU match/translate register pairs */l.movhi r5,hi(dmmu_ways)l.ori r5,r5,lo(dmmu_ways)l.lwz r3,0(r5)l.movhi r5,hi(dmmu_sets)l.ori r5,r5,lo(dmmu_sets)l.lwz r4,0(r5)l.movhi r6, 0 // Clear ways countersdmmu_clear_set:l.movhi r7, 0 // Clear sets counter// Calculate base of DMMU match & translate registersl.ori r10,r0,SPR_DTLBMR_BASE(0)l.ori r11,r0,SPR_DTLBTR_BASE(0)l.slli r5,r6,8 /* Multiply ways by 256 (ways<<8) */l.add r10,r10,r5l.add r11,r11,r5dmmu_clear_set_loop:l.mtspr r10,r0,0 /* ITLBMR_BASE(way) + set = 0 */l.mtspr r11,r0,0 /* ITLBTR_BASE(way) + set = 0 */l.addi r7,r7,1l.sfne r4,r7l.addi r10,r10,1l.bf dmmu_clear_set_loopl.addi r11,r11,1l.addi r6,r6,1 /* Increment ways counter */l.sfne r3,r6 /* Cleared all ways? */l.bf dmmu_clear_setl.nop/* Finished */l.jr r9l.nop#define TTMR_RELOAD_VALUE (SPR_TTMR_IE | SPR_TTMR_RT | TIMER_CYCLES_RATE)timer_load:l.movhi r3,hi(TTMR_RELOAD_VALUE)l.ori r3,r3,lo(TTMR_RELOAD_VALUE)l.jr r9l.mtspr r0,r3,SPR_TTMR
