Line 30... |
Line 30... |
#include "int.h"
|
#include "int.h"
|
|
|
/* Define RAM physical location and size
|
/* Define RAM physical location and size
|
Bottom half will be used for this program, the rest
|
Bottom half will be used for this program, the rest
|
will be used for testing */
|
will be used for testing */
|
#define FLASH_START 0xf0000000
|
|
#define FLASH_SIZE 0x00200000
|
|
#define RAM_START 0x00000000
|
#define RAM_START 0x00000000
|
#define RAM_SIZE 0x04000000
|
#define RAM_SIZE 0x00200000
|
|
|
#define TEST_BASE 0xa5000000
|
|
|
|
/* MMU page size */
|
/* MMU page size */
|
#define PAGE_SIZE 8192
|
#define PAGE_SIZE 8192
|
|
|
/* Number of DTLB sets used (power of 2, max is 256) */
|
/* Number of DTLB sets used (power of 2, max is 256) */
|
Line 57... |
Line 53... |
/* TLB mode codes */
|
/* TLB mode codes */
|
#define TLB_CODE_ONE_TO_ONE 0x00000000
|
#define TLB_CODE_ONE_TO_ONE 0x00000000
|
#define TLB_CODE_PLUS_ONE_PAGE 0x10000000
|
#define TLB_CODE_PLUS_ONE_PAGE 0x10000000
|
#define TLB_CODE_MINUS_ONE_PAGE 0x20000000
|
#define TLB_CODE_MINUS_ONE_PAGE 0x20000000
|
|
|
#define TLB_TEXT_SET_NB 6
|
#define TLB_TEXT_SET_NB 8
|
#define TLB_DATA_SET_NB 2
|
#define TLB_DATA_SET_NB 8
|
|
|
#define TLB_CODE_MASK 0xfffff000
|
#define TLB_CODE_MASK 0xfffff000
|
#define TLB_PR_MASK 0x00000fff
|
#define TLB_PR_MASK 0x00000fff
|
#define DTLB_PR_NOLIMIT ( SPR_DTLBTR_CI | \
|
#define DTLB_PR_NOLIMIT ( SPR_DTLBTR_CI | \
|
SPR_DTLBTR_URE | \
|
SPR_DTLBTR_URE | \
|
Line 437... |
Line 433... |
}
|
}
|
}
|
}
|
|
|
/* Set one to one translation for the use of this program */
|
/* Set one to one translation for the use of this program */
|
for (i = 0; i < TLB_TEXT_SET_NB; i++) {
|
for (i = 0; i < TLB_TEXT_SET_NB; i++) {
|
ea = FLASH_START + (i*PAGE_SIZE);
|
ea = RAM_START + (i*PAGE_SIZE);
|
ta = FLASH_START + (i*PAGE_SIZE);
|
ta = RAM_START + (i*PAGE_SIZE);
|
mtspr (SPR_ITLBMR_BASE(0) + i, ea | SPR_ITLBMR_V);
|
mtspr (SPR_ITLBMR_BASE(0) + i, ea | SPR_ITLBMR_V);
|
mtspr (SPR_ITLBTR_BASE(0) + i, ta | ITLB_PR_NOLIMIT);
|
mtspr (SPR_ITLBTR_BASE(0) + i, ta | ITLB_PR_NOLIMIT);
|
}
|
}
|
|
|
/* Set dtlb no permisions */
|
/* Set dtlb no permisions */
|
Line 625... |
Line 621... |
}
|
}
|
}
|
}
|
|
|
/* Set one to one translation for the use of this program */
|
/* Set one to one translation for the use of this program */
|
for (i = 0; i < TLB_TEXT_SET_NB; i++) {
|
for (i = 0; i < TLB_TEXT_SET_NB; i++) {
|
ea = FLASH_START + (i*PAGE_SIZE);
|
ea = RAM_START + (i*PAGE_SIZE);
|
ta = FLASH_START + (i*PAGE_SIZE);
|
ta = RAM_START + (i*PAGE_SIZE);
|
mtspr (SPR_ITLBMR_BASE(0) + i, ea | SPR_ITLBMR_V);
|
mtspr (SPR_ITLBMR_BASE(0) + i, ea | SPR_ITLBMR_V);
|
mtspr (SPR_ITLBTR_BASE(0) + i, ta | ITLB_PR_NOLIMIT);
|
mtspr (SPR_ITLBTR_BASE(0) + i, ta | ITLB_PR_NOLIMIT);
|
}
|
}
|
|
|
/* Invalidate all entries in DTLB */
|
/* Invalidate all entries in DTLB */
|
Line 656... |
Line 652... |
except_ea = 0;
|
except_ea = 0;
|
|
|
/* Set IMMU translation */
|
/* Set IMMU translation */
|
ea = RAM_START + (RAM_SIZE) + ((TLB_TEXT_SET_NB)*PAGE_SIZE);
|
ea = RAM_START + (RAM_SIZE) + ((TLB_TEXT_SET_NB)*PAGE_SIZE);
|
itlb_val = SPR_ITLBTR_CI | SPR_ITLBTR_SXE;
|
itlb_val = SPR_ITLBTR_CI | SPR_ITLBTR_SXE;
|
mtspr (SPR_ITLBMR_BASE(0) + TLB_TEXT_SET_NB, (ea & SPR_ITLBMR_VPN) | SPR_ITLBMR_V);
|
mtspr (SPR_ITLBMR_BASE(0) + TLB_TEXT_SET_NB, (ea & SPR_ITLBMR_VPN) |
|
mtspr (SPR_ITLBTR_BASE(0) + TLB_TEXT_SET_NB, ((ea + PAGE_SIZE) & SPR_ITLBTR_PPN) | itlb_val);
|
SPR_ITLBMR_V);
|
|
// Set translate to invalid address: 0xee000000
|
|
mtspr (SPR_ITLBTR_BASE(0) + TLB_TEXT_SET_NB, (0xee000000 & SPR_ITLBTR_PPN) |
|
|
itlb_val);
|
|
|
/* Enable IMMU */
|
/* Enable IMMU */
|
immu_enable ();
|
immu_enable ();
|
|
|
/* Check if there was bus error exception */
|
/* Check if there was bus error exception */
|
Line 678... |
Line 677... |
except_count = 0;
|
except_count = 0;
|
except_mask = 0;
|
except_mask = 0;
|
except_pc = 0;
|
except_pc = 0;
|
except_ea = 0;
|
except_ea = 0;
|
|
|
/* Copy jump instruction to last location of RAM */
|
/* Set EA as an invalid memory location */
|
ea = RAM_START + RAM_SIZE - 8;
|
ea = 0xee000000;
|
memcpy((void *)ea, (void *)&jump_back, 8);
|
|
|
|
/* Check if there was bus error exception */
|
/* Check if there was bus error exception */
|
ret = call (ea, 0);
|
ret = call (ea, 0);
|
ASSERT(except_count == 1);
|
ASSERT(except_count == 1);
|
ASSERT(except_mask == (1 << V_BERR));
|
ASSERT(except_mask == (1 << V_BERR));
|
ASSERT(except_pc == ea + 4);
|
ASSERT(except_pc == ea);
|
ASSERT(except_ea == ea + 8);
|
ASSERT(except_ea == ea);
|
|
|
/* Reset except counter */
|
/* Reset except counter */
|
except_count = 0;
|
except_count = 0;
|
except_mask = 0;
|
except_mask = 0;
|
except_pc = 0;
|
except_pc = 0;
|
except_ea = 0;
|
except_ea = 0;
|
|
|
/* Set DMMU translation */
|
/* Set DMMU translation */
|
ea = RAM_START + (RAM_SIZE) + ((TLB_DATA_SET_NB)*PAGE_SIZE);
|
ea = RAM_START + (RAM_SIZE) + ((TLB_DATA_SET_NB)*PAGE_SIZE);
|
dtlb_val = SPR_DTLBTR_CI | SPR_DTLBTR_SRE;
|
dtlb_val = SPR_DTLBTR_CI | SPR_DTLBTR_SRE;
|
mtspr (SPR_DTLBMR_BASE(0) + TLB_DATA_SET_NB, (ea & SPR_DTLBMR_VPN) | SPR_DTLBMR_V);
|
mtspr (SPR_DTLBMR_BASE(0) + TLB_DATA_SET_NB, (ea & SPR_DTLBMR_VPN) |
|
mtspr (SPR_DTLBTR_BASE(0) + TLB_DATA_SET_NB, ((ea + PAGE_SIZE) & SPR_DTLBTR_PPN) | dtlb_val);
|
SPR_DTLBMR_V);
|
|
// Set translate to invalid address: 0xee000000
|
|
mtspr (SPR_DTLBTR_BASE(0) + TLB_DATA_SET_NB, (0xee000000 & SPR_DTLBTR_PPN) |
|
|
dtlb_val);
|
|
|
/* Enable DMMU */
|
/* Enable DMMU */
|
dmmu_enable ();
|
dmmu_enable ();
|
|
|
/* Check if there was bus error exception */
|
/* Check if there was bus error exception */
|
Line 721... |
Line 722... |
except_count = 0;
|
except_count = 0;
|
except_mask = 0;
|
except_mask = 0;
|
except_pc = 0;
|
except_pc = 0;
|
except_ea = 0;
|
except_ea = 0;
|
|
|
|
// Set ea to invalid address
|
|
ea = 0xee000000;
|
|
|
/* Check if there was bus error exception */
|
/* Check if there was bus error exception */
|
ret = call ((unsigned long)&load_acc_32, ea );
|
ret = call ((unsigned long)&load_acc_32, ea );
|
ASSERT(except_count == 1);
|
ASSERT(except_count == 1);
|
ASSERT(except_mask == (1 << V_BERR));
|
ASSERT(except_mask == (1 << V_BERR));
|
ASSERT(except_pc == (unsigned long)load_acc_32 + 8);
|
ASSERT(except_pc == (unsigned long)load_acc_32 + 8);
|
Line 751... |
Line 755... |
rather than the immediately preceding l.jr r9 (allowing us to
|
rather than the immediately preceding l.jr r9 (allowing us to
|
recover). Secondly it used 0xffffffff as an illegal instruction. Except
|
recover). Secondly it used 0xffffffff as an illegal instruction. Except
|
it isn't - it's l.cust8 0x3ffffff.
|
it isn't - it's l.cust8 0x3ffffff.
|
|
|
Fixed by a) jumping to the correct location and b) really using an
|
Fixed by a) jumping to the correct location and b) really using an
|
illegal instruction. */
|
illegal instruction (opcode 0x3a. */
|
REG32(RAM_START + (RAM_SIZE/2)) = REG32((unsigned long)jump_back + 4);
|
REG32(RAM_START + (RAM_SIZE/2)) = REG32((unsigned long)jump_back + 4);
|
REG32(RAM_START + (RAM_SIZE/2) + 4) = 0xe5dfffff;
|
REG32(RAM_START + (RAM_SIZE/2) + 4) = 0xe8000000;
|
|
|
/* Check if there was illegal insn exception. Note that if an illegal
|
/* Check if there was illegal insn exception. Note that if an illegal
|
instruction occurs in a delay slot (like this one), then the exception
|
instruction occurs in a delay slot (like this one), then the exception
|
PC is the address of the hump instruction. */
|
PC is the address of the jump instruction. */
|
ret = call (RAM_START + (RAM_SIZE/2), 0 ); /* JPB */
|
ret = call (RAM_START + (RAM_SIZE/2), 0 ); /* JPB */
|
|
|
ASSERT(except_count == 1);
|
ASSERT(except_count == 1);
|
ASSERT(except_mask == (1 << V_ILLINSN));
|
ASSERT(except_mask == (1 << V_ILLINSN));
|
ASSERT(except_pc == (RAM_START + (RAM_SIZE/2)));
|
ASSERT(except_pc == (RAM_START + (RAM_SIZE/2)));
|
Line 911... |
Line 915... |
}
|
}
|
}
|
}
|
|
|
/* Set one to one translation for the use of this program */
|
/* Set one to one translation for the use of this program */
|
for (i = 0; i < TLB_TEXT_SET_NB; i++) {
|
for (i = 0; i < TLB_TEXT_SET_NB; i++) {
|
ea = FLASH_START + (i*PAGE_SIZE);
|
ea = RAM_START + (i*PAGE_SIZE);
|
ta = FLASH_START + (i*PAGE_SIZE);
|
ta = RAM_START + (i*PAGE_SIZE);
|
mtspr (SPR_ITLBMR_BASE(0) + i, ea | SPR_ITLBMR_V);
|
mtspr (SPR_ITLBMR_BASE(0) + i, ea | SPR_ITLBMR_V);
|
mtspr (SPR_ITLBTR_BASE(0) + i, ta | ITLB_PR_NOLIMIT);
|
mtspr (SPR_ITLBTR_BASE(0) + i, ta | ITLB_PR_NOLIMIT);
|
}
|
}
|
|
|
/* Set dtlb no permisions */
|
/* Set dtlb no permisions */
|
Line 951... |
Line 955... |
except_ea = 0;
|
except_ea = 0;
|
|
|
/* Enable IMMU */
|
/* Enable IMMU */
|
immu_enable ();
|
immu_enable ();
|
|
|
|
/* The following is currently disabled due to differing behavior between
|
|
or1ksim and the OR1200 RTL. Or1ksim appears to receive only 1 exception
|
|
during the call_with_int() call. The OR1200 correctly, in my opionion,
|
|
reports 2 exceptions - ITLB miss and tick timer. -- Julius
|
|
|
|
TODO: Investigate why or1ksim isn't reporting ITLB miss.
|
|
|
|
*/
|
|
|
|
#if 0
|
/* Check if there was INT exception */
|
/* Check if there was INT exception */
|
call_with_int (RAM_START + (RAM_SIZE) + (TLB_TEXT_SET_NB*PAGE_SIZE), 0);
|
call_with_int (RAM_START + (RAM_SIZE) + (TLB_TEXT_SET_NB*PAGE_SIZE), 0);
|
ASSERT(except_count == 1);
|
printf("ec:%d 0x%lx\n",except_count,except_mask); ASSERT(except_count == 2);
|
ASSERT(except_mask == (1 << V_TICK));
|
ASSERT(except_mask == ((1 << V_TICK) | (1 << V_ITLB_MISS)));
|
|
printf("epc %8lx\n",except_pc);
|
ASSERT(except_pc == (RAM_START + (RAM_SIZE) + (TLB_TEXT_SET_NB*PAGE_SIZE)));
|
ASSERT(except_pc == (RAM_START + (RAM_SIZE) + (TLB_TEXT_SET_NB*PAGE_SIZE)));
|
|
|
/* Reset except counter */
|
/* Reset except counter */
|
except_count = 0;
|
except_count = 0;
|
except_mask = 0;
|
except_mask = 0;
|
except_pc = 0;
|
except_pc = 0;
|
except_ea = 0;
|
except_ea = 0;
|
|
#endif
|
|
|
/* Check if there was ITLB exception */
|
/* Check if there was ITLB exception */
|
call (RAM_START + (RAM_SIZE) + (TLB_TEXT_SET_NB*PAGE_SIZE), 0);
|
call (RAM_START + (RAM_SIZE) + (TLB_TEXT_SET_NB*PAGE_SIZE), 0);
|
ASSERT(except_count == 1);
|
ASSERT(except_count == 1);
|
ASSERT(except_mask == (1 << V_ITLB_MISS));
|
ASSERT(except_mask == (1 << V_ITLB_MISS));
|
Line 992... |
Line 1008... |
except_count = 0;
|
except_count = 0;
|
except_mask = 0;
|
except_mask = 0;
|
except_pc = 0;
|
except_pc = 0;
|
except_ea = 0;
|
except_ea = 0;
|
|
|
/* Check if there was bus error exception */
|
|
call (RAM_START + (RAM_SIZE) + (TLB_TEXT_SET_NB*PAGE_SIZE), 0);
|
|
ASSERT(except_count == 1);
|
|
ASSERT(except_mask == (1 << V_BERR));
|
|
ASSERT(except_pc == (RAM_START + (RAM_SIZE) + (TLB_TEXT_SET_NB*PAGE_SIZE)));
|
|
ASSERT(except_ea == (RAM_START + (RAM_SIZE) + (TLB_TEXT_SET_NB*PAGE_SIZE)));
|
|
|
|
/* Reset except counter */
|
|
except_count = 0;
|
|
except_mask = 0;
|
|
except_pc = 0;
|
|
except_ea = 0;
|
|
|
|
/* Disable MMU */
|
/* Disable MMU */
|
immu_disable ();
|
immu_disable ();
|
|
|
/* Set illegal instruction. JPB. Use a really illegal instruction, not
|
/* Set illegal instruction. JPB. Use a really illegal instruction, not
|
l.cust8 0x3ffffff. */
|
l.cust8 0x3ffffff. */
|
REG32(RAM_START + (RAM_SIZE/2) + (TLB_TEXT_SET_NB*PAGE_SIZE) + 0) = 0x00000000;
|
REG32(RAM_START + (RAM_SIZE/2) + (TLB_TEXT_SET_NB*PAGE_SIZE) + 0) = 0x00000000;
|
REG32(RAM_START + (RAM_SIZE/2) + (TLB_TEXT_SET_NB*PAGE_SIZE) + 4) = 0xe5dfffff;
|
REG32(RAM_START + (RAM_SIZE/2) + (TLB_TEXT_SET_NB*PAGE_SIZE) + 4) = 0xe8000000;
|
REG32(RAM_START + (RAM_SIZE/2) + (TLB_TEXT_SET_NB*PAGE_SIZE) + 8) = 0x00000000;
|
REG32(RAM_START + (RAM_SIZE/2) + (TLB_TEXT_SET_NB*PAGE_SIZE) + 8) = 0x00000000;
|
|
|
/* Check if there was illegal insn exception */
|
/* Check if there was illegal insn exception */
|
call (RAM_START + (RAM_SIZE/2) + (TLB_TEXT_SET_NB*PAGE_SIZE) + 4, 0);
|
call (RAM_START + (RAM_SIZE/2) + (TLB_TEXT_SET_NB*PAGE_SIZE) + 4, 0);
|
ASSERT(except_count == 1);
|
ASSERT(except_count == 1);
|
Line 1075... |
Line 1078... |
except_count = 0;
|
except_count = 0;
|
except_mask = 0;
|
except_mask = 0;
|
except_pc = 0;
|
except_pc = 0;
|
except_ea = 0;
|
except_ea = 0;
|
|
|
/* Check if there was bus error exception */
|
|
ret = call ((unsigned long)&load_acc_32, RAM_START + (RAM_SIZE) + (TLB_DATA_SET_NB*PAGE_SIZE));
|
|
ASSERT(except_count == 1);
|
|
ASSERT(except_mask == (1 << V_BERR));
|
|
ASSERT(ret == 0x12345678);
|
|
ASSERT(except_pc == ((unsigned long)(load_acc_32) + 8));
|
|
ASSERT(except_ea == (RAM_START + (RAM_SIZE) + (TLB_DATA_SET_NB*PAGE_SIZE)));
|
|
|
|
/* Reset except counter */
|
|
except_count = 0;
|
|
except_mask = 0;
|
|
except_pc = 0;
|
|
except_ea = 0;
|
|
|
|
/* Check if there was trap exception */
|
/* Check if there was trap exception */
|
call ((unsigned long)&trap, 0);
|
call ((unsigned long)&trap, 0);
|
ASSERT(except_count == 1);
|
ASSERT(except_count == 1);
|
ASSERT(except_mask == (1 << V_TRAP));
|
ASSERT(except_mask == (1 << V_TRAP));
|
ASSERT(except_pc == (unsigned long)(trap));
|
ASSERT(except_pc == (unsigned long)(trap));
|
Line 1139... |
Line 1128... |
excpt_range = (unsigned long)range_handler;
|
excpt_range = (unsigned long)range_handler;
|
|
|
/* Exception basic test */
|
/* Exception basic test */
|
ret = except_basic ();
|
ret = except_basic ();
|
ASSERT(ret == 0);
|
ASSERT(ret == 0);
|
|
printf("interupt_test\n");
|
/* Interrupt exception test */
|
/* Interrupt exception test */
|
interrupt_test ();
|
interrupt_test ();
|
|
|
|
printf("itlb_test\n");
|
/* ITLB exception test */
|
/* ITLB exception test */
|
itlb_test ();
|
itlb_test ();
|
|
|
printf("dtlb_test\n");
|
printf("dtlb_test\n");
|
/* DTLB exception test */
|
/* DTLB exception test */
|