mirror of
https://github.com/antonblanchard/microwatt.git
synced 2026-01-28 04:37:45 +00:00
tests: mmu: Add tests for instruction translation
This adds tests of instruction translation to the mmu test. This also clears the BSS and improves the linker script. Signed-off-by: Paul Mackerras <paulus@ozlabs.org>
This commit is contained in:
@@ -14,8 +14,6 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#define STACK_TOP 0x4000
|
||||
|
||||
/* Load an immediate 64-bit value into a register */
|
||||
#define LOAD_IMM64(r, e) \
|
||||
lis r,(e)@highest; \
|
||||
@@ -33,12 +31,20 @@
|
||||
. = 0
|
||||
.global _start
|
||||
_start:
|
||||
b boot_entry
|
||||
LOAD_IMM64(%r10,__bss_start)
|
||||
LOAD_IMM64(%r11,__bss_end)
|
||||
subf %r11,%r10,%r11
|
||||
addi %r11,%r11,63
|
||||
srdi. %r11,%r11,6
|
||||
beq 2f
|
||||
mtctr %r11
|
||||
1: dcbz 0,%r10
|
||||
addi %r10,%r10,64
|
||||
bdnz 1b
|
||||
|
||||
.global boot_entry
|
||||
boot_entry:
|
||||
/* setup stack */
|
||||
LOAD_IMM64(%r1, STACK_TOP - 0x100)
|
||||
2: LOAD_IMM64(%r1,__stack_top)
|
||||
li %r0,0
|
||||
stdu %r0,-16(%r1)
|
||||
LOAD_IMM64(%r12, main)
|
||||
mtctr %r12
|
||||
bctrl
|
||||
@@ -74,6 +80,12 @@ test_write:
|
||||
mtmsrd %r9,0
|
||||
blr
|
||||
|
||||
.globl test_exec
|
||||
test_exec:
|
||||
mtsrr0 %r4
|
||||
mtsrr1 %r5
|
||||
rfid
|
||||
|
||||
#define EXCEPTION(nr) \
|
||||
.= nr ;\
|
||||
attn
|
||||
@@ -86,9 +98,17 @@ test_write:
|
||||
mtsrr0 %r10
|
||||
rfid
|
||||
|
||||
/* More exception stubs */
|
||||
EXCEPTION(0x380)
|
||||
EXCEPTION(0x400)
|
||||
|
||||
/*
|
||||
* ISI vector - jump to LR to return from the test,
|
||||
* with r3 cleared
|
||||
*/
|
||||
. = 0x400
|
||||
li %r3,0
|
||||
blr
|
||||
|
||||
/* More exception stubs */
|
||||
EXCEPTION(0x480)
|
||||
EXCEPTION(0x500)
|
||||
EXCEPTION(0x600)
|
||||
@@ -98,7 +118,14 @@ test_write:
|
||||
EXCEPTION(0x980)
|
||||
EXCEPTION(0xa00)
|
||||
EXCEPTION(0xb00)
|
||||
EXCEPTION(0xc00)
|
||||
|
||||
/*
|
||||
* System call - used to exit from tests where MSR[PR]
|
||||
* may have been set.
|
||||
*/
|
||||
. = 0xc00
|
||||
blr
|
||||
|
||||
EXCEPTION(0xd00)
|
||||
EXCEPTION(0xe00)
|
||||
EXCEPTION(0xe20)
|
||||
@@ -110,3 +137,29 @@ test_write:
|
||||
EXCEPTION(0xf40)
|
||||
EXCEPTION(0xf60)
|
||||
EXCEPTION(0xf80)
|
||||
|
||||
. = 0x1000
|
||||
/*
|
||||
* This page gets mapped at various locations and
|
||||
* the tests try to execute from it.
|
||||
* r3 contains the test number.
|
||||
*/
|
||||
.globl test_start
|
||||
test_start:
|
||||
nop
|
||||
nop
|
||||
cmpdi %r3,1
|
||||
beq test_1
|
||||
cmpdi %r3,2
|
||||
beq test_2
|
||||
test_return:
|
||||
li %r3,1
|
||||
sc
|
||||
|
||||
. = 0x1ff8
|
||||
/* test a branch near the end of a page */
|
||||
test_1: b test_return
|
||||
|
||||
/* test flowing from one page to the next */
|
||||
test_2: nop
|
||||
b test_return
|
||||
|
||||
226
tests/mmu/mmu.c
226
tests/mmu/mmu.c
@@ -4,14 +4,23 @@
|
||||
|
||||
#include "console.h"
|
||||
|
||||
#define MSR_DR 0x10
|
||||
#define MSR_IR 0x20
|
||||
|
||||
extern int test_read(long *addr, long *ret, long init);
|
||||
extern int test_write(long *addr, long val);
|
||||
extern int test_exec(int testno, unsigned long pc, unsigned long msr);
|
||||
|
||||
static inline void do_tlbie(unsigned long rb, unsigned long rs)
|
||||
{
|
||||
__asm__ volatile("tlbie %0,%1" : : "r" (rb), "r" (rs) : "memory");
|
||||
}
|
||||
|
||||
#define DSISR 18
|
||||
#define DAR 19
|
||||
#define SRR0 26
|
||||
#define SRR1 27
|
||||
|
||||
static inline unsigned long mfspr(int sprnum)
|
||||
{
|
||||
long val;
|
||||
@@ -135,6 +144,8 @@ void map(void *ea, void *pa, unsigned long perm_attr)
|
||||
free_ptr += 512 * sizeof(unsigned long);
|
||||
}
|
||||
ptep = read_pgd(i);
|
||||
if (ptep[j])
|
||||
do_tlbie(((unsigned long)ea & ~0xfff), 0);
|
||||
store_pte(&ptep[j], 0xc000000000000000 | ((unsigned long)pa & 0x00fffffffffff000) | perm_attr);
|
||||
eas_mapped[neas_mapped++] = ea;
|
||||
}
|
||||
@@ -175,14 +186,14 @@ int mmu_test_1(void)
|
||||
if (val != 0xdeadbeefd00d)
|
||||
return 2;
|
||||
/* DAR and DSISR should be set correctly */
|
||||
if (mfspr(19) != (long) ptr || mfspr(18) != 0x40000000)
|
||||
if (mfspr(DAR) != (long) ptr || mfspr(DSISR) != 0x40000000)
|
||||
return 3;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mmu_test_2(void)
|
||||
{
|
||||
long *mem = (long *) 0x4000;
|
||||
long *mem = (long *) 0x8000;
|
||||
long *ptr = (long *) 0x124000;
|
||||
long *ptr2 = (long *) 0x1124000;
|
||||
long val;
|
||||
@@ -215,8 +226,8 @@ int mmu_test_2(void)
|
||||
|
||||
int mmu_test_3(void)
|
||||
{
|
||||
long *mem = (long *) 0x5000;
|
||||
long *ptr = (long *) 0x149000;
|
||||
long *mem = (long *) 0x9000;
|
||||
long *ptr = (long *) 0x14a000;
|
||||
long val;
|
||||
|
||||
/* create PTE */
|
||||
@@ -238,16 +249,16 @@ int mmu_test_3(void)
|
||||
if (val != 0xdeadbeefd0d0)
|
||||
return 4;
|
||||
/* DAR and DSISR should be set correctly */
|
||||
if (mfspr(19) != (long) &ptr[45] || mfspr(18) != 0x40000000)
|
||||
if (mfspr(DAR) != (long) &ptr[45] || mfspr(DSISR) != 0x40000000)
|
||||
return 5;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mmu_test_4(void)
|
||||
{
|
||||
long *mem = (long *) 0x6000;
|
||||
long *ptr = (long *) 0x10a000;
|
||||
long *ptr2 = (long *) 0x110a000;
|
||||
long *mem = (long *) 0xa000;
|
||||
long *ptr = (long *) 0x10b000;
|
||||
long *ptr2 = (long *) 0x110b000;
|
||||
long val;
|
||||
|
||||
/* create PTE */
|
||||
@@ -279,7 +290,7 @@ int mmu_test_4(void)
|
||||
|
||||
int mmu_test_5(void)
|
||||
{
|
||||
long *mem = (long *) 0x7ffd;
|
||||
long *mem = (long *) 0xbffd;
|
||||
long *ptr = (long *) 0x39fffd;
|
||||
long val;
|
||||
|
||||
@@ -292,14 +303,14 @@ int mmu_test_5(void)
|
||||
if (val != 0xdeadbeef0dd0)
|
||||
return 2;
|
||||
/* DAR and DSISR should be set correctly */
|
||||
if (mfspr(19) != ((long)ptr & ~0xfff) + 0x1000 || mfspr(18) != 0x40000000)
|
||||
if (mfspr(DAR) != ((long)ptr & ~0xfff) + 0x1000 || mfspr(DSISR) != 0x40000000)
|
||||
return 3;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mmu_test_6(void)
|
||||
{
|
||||
long *mem = (long *) 0x7ffd;
|
||||
long *mem = (long *) 0xbffd;
|
||||
long *ptr = (long *) 0x39fffd;
|
||||
|
||||
/* create PTE */
|
||||
@@ -310,14 +321,14 @@ int mmu_test_6(void)
|
||||
if (test_write(ptr, 0xdeadbeef0dd0))
|
||||
return 1;
|
||||
/* DAR and DSISR should be set correctly */
|
||||
if (mfspr(19) != ((long)ptr & ~0xfff) + 0x1000 || mfspr(18) != 0x42000000)
|
||||
if (mfspr(DAR) != ((long)ptr & ~0xfff) + 0x1000 || mfspr(DSISR) != 0x42000000)
|
||||
return 2;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mmu_test_7(void)
|
||||
{
|
||||
long *mem = (long *) 0x4000;
|
||||
long *mem = (long *) 0x8000;
|
||||
long *ptr = (long *) 0x124000;
|
||||
long val;
|
||||
|
||||
@@ -331,13 +342,13 @@ int mmu_test_7(void)
|
||||
if (val != 0xdeadd00dbeef)
|
||||
return 2;
|
||||
/* DAR and DSISR should be set correctly */
|
||||
if (mfspr(19) != (long) ptr || mfspr(18) != 0x00040000)
|
||||
if (mfspr(DAR) != (long) ptr || mfspr(DSISR) != 0x00040000)
|
||||
return 3;
|
||||
/* this should fail */
|
||||
if (test_write(ptr, 0xdeadbeef0dd0))
|
||||
return 4;
|
||||
/* DAR and DSISR should be set correctly */
|
||||
if (mfspr(19) != (long)ptr || mfspr(18) != 0x02040000)
|
||||
if (mfspr(DAR) != (long)ptr || mfspr(DSISR) != 0x02040000)
|
||||
return 5;
|
||||
/* memory should be unchanged */
|
||||
if (*mem != 0x123456789abcdef0)
|
||||
@@ -347,7 +358,7 @@ int mmu_test_7(void)
|
||||
|
||||
int mmu_test_8(void)
|
||||
{
|
||||
long *mem = (long *) 0x4000;
|
||||
long *mem = (long *) 0x8000;
|
||||
long *ptr = (long *) 0x124000;
|
||||
long val;
|
||||
|
||||
@@ -361,7 +372,7 @@ int mmu_test_8(void)
|
||||
if (test_write(ptr, 0xdeadbeef0dd1))
|
||||
return 2;
|
||||
/* DAR and DSISR should be set correctly */
|
||||
if (mfspr(19) != (long)ptr || mfspr(18) != 0x02040000)
|
||||
if (mfspr(DAR) != (long)ptr || mfspr(DSISR) != 0x02040000)
|
||||
return 3;
|
||||
/* memory should be unchanged */
|
||||
if (*mem != 0x123456789abcdef0)
|
||||
@@ -371,7 +382,7 @@ int mmu_test_8(void)
|
||||
|
||||
int mmu_test_9(void)
|
||||
{
|
||||
long *mem = (long *) 0x4000;
|
||||
long *mem = (long *) 0x8000;
|
||||
long *ptr = (long *) 0x124000;
|
||||
long val;
|
||||
|
||||
@@ -385,13 +396,13 @@ int mmu_test_9(void)
|
||||
if (val != 0xdeadd00dbeef)
|
||||
return 2;
|
||||
/* DAR and DSISR should be set correctly */
|
||||
if (mfspr(19) != (long) ptr || mfspr(18) != 0x08000000)
|
||||
if (mfspr(DAR) != (long) ptr || mfspr(DSISR) != 0x08000000)
|
||||
return 3;
|
||||
/* this should fail */
|
||||
if (test_write(ptr, 0xdeadbeef0dd1))
|
||||
return 4;
|
||||
/* DAR and DSISR should be set correctly */
|
||||
if (mfspr(19) != (long)ptr || mfspr(18) != 0x0a000000)
|
||||
if (mfspr(DAR) != (long)ptr || mfspr(DSISR) != 0x0a000000)
|
||||
return 5;
|
||||
/* memory should be unchanged */
|
||||
if (*mem != 0x123456789abcdef0)
|
||||
@@ -401,7 +412,7 @@ int mmu_test_9(void)
|
||||
|
||||
int mmu_test_10(void)
|
||||
{
|
||||
long *mem = (long *) 0x4000;
|
||||
long *mem = (long *) 0x8000;
|
||||
long *ptr = (long *) 0x124000;
|
||||
long val;
|
||||
|
||||
@@ -415,7 +426,7 @@ int mmu_test_10(void)
|
||||
if (test_write(ptr, 0xdeadbeef0dd1))
|
||||
return 2;
|
||||
/* DAR and DSISR should be set correctly */
|
||||
if (mfspr(19) != (long)ptr || mfspr(18) != 0x0a000000)
|
||||
if (mfspr(DAR) != (long)ptr || mfspr(DSISR) != 0x0a000000)
|
||||
return 3;
|
||||
/* memory should be unchanged */
|
||||
if (*mem != 0x123456789abcdef0)
|
||||
@@ -423,14 +434,159 @@ int mmu_test_10(void)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mmu_test_11(void)
|
||||
{
|
||||
unsigned long ptr = 0x523000;
|
||||
|
||||
/* this should fail */
|
||||
if (test_exec(0, ptr, MSR_IR))
|
||||
return 1;
|
||||
/* SRR0 and SRR1 should be set correctly */
|
||||
if (mfspr(SRR0) != (long) ptr || mfspr(SRR1) != 0x40000020)
|
||||
return 2;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mmu_test_12(void)
|
||||
{
|
||||
unsigned long mem = 0x1000;
|
||||
unsigned long ptr = 0x324000;
|
||||
unsigned long ptr2 = 0x1324000;
|
||||
|
||||
/* create PTE */
|
||||
map((void *)ptr, (void *)mem, PERM_EX | REF);
|
||||
/* this should succeed and be a cache miss */
|
||||
if (!test_exec(0, ptr, MSR_IR))
|
||||
return 1;
|
||||
/* create a second PTE */
|
||||
map((void *)ptr2, (void *)mem, PERM_EX | REF);
|
||||
/* this should succeed and be a cache hit */
|
||||
if (!test_exec(0, ptr2, MSR_IR))
|
||||
return 2;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mmu_test_13(void)
|
||||
{
|
||||
unsigned long mem = 0x1000;
|
||||
unsigned long ptr = 0x349000;
|
||||
unsigned long ptr2 = 0x34a000;
|
||||
|
||||
/* create a PTE */
|
||||
map((void *)ptr, (void *)mem, PERM_EX | REF);
|
||||
/* this should succeed */
|
||||
if (!test_exec(1, ptr, MSR_IR))
|
||||
return 1;
|
||||
/* invalidate the PTE */
|
||||
unmap((void *)ptr);
|
||||
/* install a second PTE */
|
||||
map((void *)ptr2, (void *)mem, PERM_EX | REF);
|
||||
/* this should fail */
|
||||
if (test_exec(1, ptr, MSR_IR))
|
||||
return 2;
|
||||
/* SRR0 and SRR1 should be set correctly */
|
||||
if (mfspr(SRR0) != (long) ptr || mfspr(SRR1) != 0x40000020)
|
||||
return 3;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mmu_test_14(void)
|
||||
{
|
||||
unsigned long mem = 0x1000;
|
||||
unsigned long mem2 = 0x2000;
|
||||
unsigned long ptr = 0x30a000;
|
||||
unsigned long ptr2 = 0x30b000;
|
||||
|
||||
/* create a PTE */
|
||||
map((void *)ptr, (void *)mem, PERM_EX | REF);
|
||||
/* this should fail due to second page not being mapped */
|
||||
if (test_exec(2, ptr, MSR_IR))
|
||||
return 1;
|
||||
/* SRR0 and SRR1 should be set correctly */
|
||||
if (mfspr(SRR0) != ptr2 || mfspr(SRR1) != 0x40000020)
|
||||
return 2;
|
||||
/* create a PTE for the second page */
|
||||
map((void *)ptr2, (void *)mem2, PERM_EX | REF);
|
||||
/* this should succeed */
|
||||
if (!test_exec(2, ptr, MSR_IR))
|
||||
return 3;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mmu_test_15(void)
|
||||
{
|
||||
unsigned long mem = 0x1000;
|
||||
unsigned long ptr = 0x324000;
|
||||
|
||||
/* create a PTE without execute permission */
|
||||
map((void *)ptr, (void *)mem, DFLT_PERM);
|
||||
/* this should fail */
|
||||
if (test_exec(0, ptr, MSR_IR))
|
||||
return 1;
|
||||
/* SRR0 and SRR1 should be set correctly */
|
||||
if (mfspr(SRR0) != ptr || mfspr(SRR1) != 0x10000020)
|
||||
return 2;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mmu_test_16(void)
|
||||
{
|
||||
unsigned long mem = 0x1000;
|
||||
unsigned long mem2 = 0x2000;
|
||||
unsigned long ptr = 0x30a000;
|
||||
unsigned long ptr2 = 0x30b000;
|
||||
|
||||
/* create a PTE */
|
||||
map((void *)ptr, (void *)mem, PERM_EX | REF);
|
||||
/* create a PTE for the second page without execute permission */
|
||||
map((void *)ptr2, (void *)mem2, PERM_RD | REF);
|
||||
/* this should fail due to second page being no-execute */
|
||||
if (test_exec(2, ptr, MSR_IR))
|
||||
return 1;
|
||||
/* SRR0 and SRR1 should be set correctly */
|
||||
if (mfspr(SRR0) != ptr2 || mfspr(SRR1) != 0x10000020)
|
||||
return 2;
|
||||
/* create a PTE for the second page with execute permission */
|
||||
map((void *)ptr2, (void *)mem2, PERM_RD | PERM_EX | REF);
|
||||
/* this should succeed */
|
||||
if (!test_exec(2, ptr, MSR_IR))
|
||||
return 3;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mmu_test_17(void)
|
||||
{
|
||||
unsigned long mem = 0x1000;
|
||||
unsigned long ptr = 0x349000;
|
||||
|
||||
/* create a PTE without the ref bit set */
|
||||
map((void *)ptr, (void *)mem, PERM_EX);
|
||||
/* this should fail */
|
||||
if (test_exec(2, ptr, MSR_IR))
|
||||
return 1;
|
||||
/* SRR0 and SRR1 should be set correctly */
|
||||
if (mfspr(SRR0) != (long) ptr || mfspr(SRR1) != 0x00040020)
|
||||
return 2;
|
||||
/* create a PTE without ref or execute permission */
|
||||
map((void *)ptr, (void *)mem, 0);
|
||||
/* this should fail */
|
||||
if (test_exec(2, ptr, MSR_IR))
|
||||
return 1;
|
||||
/* SRR0 and SRR1 should be set correctly */
|
||||
/* RC update fail bit should not be set */
|
||||
if (mfspr(SRR0) != (long) ptr || mfspr(SRR1) != 0x10000020)
|
||||
return 2;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int fail = 0;
|
||||
|
||||
void do_test(int num, int (*test)(void))
|
||||
{
|
||||
int ret;
|
||||
|
||||
mtspr(18, 0);
|
||||
mtspr(19, 0);
|
||||
mtspr(DSISR, 0);
|
||||
mtspr(DAR, 0);
|
||||
unmap_all();
|
||||
print_test_number(num);
|
||||
ret = test();
|
||||
@@ -440,10 +596,17 @@ void do_test(int num, int (*test)(void))
|
||||
fail = 1;
|
||||
print_string("FAIL ");
|
||||
putchar(ret + '0');
|
||||
print_string(" DAR=");
|
||||
print_hex(mfspr(19));
|
||||
print_string(" DSISR=");
|
||||
print_hex(mfspr(18));
|
||||
if (num <= 10) {
|
||||
print_string(" DAR=");
|
||||
print_hex(mfspr(DAR));
|
||||
print_string(" DSISR=");
|
||||
print_hex(mfspr(DSISR));
|
||||
} else {
|
||||
print_string(" SRR0=");
|
||||
print_hex(mfspr(SRR0));
|
||||
print_string(" SRR1=");
|
||||
print_hex(mfspr(SRR1));
|
||||
}
|
||||
print_string("\r\n");
|
||||
}
|
||||
}
|
||||
@@ -463,6 +626,13 @@ int main(void)
|
||||
do_test(8, mmu_test_8);
|
||||
do_test(9, mmu_test_9);
|
||||
do_test(10, mmu_test_10);
|
||||
do_test(11, mmu_test_11);
|
||||
do_test(12, mmu_test_12);
|
||||
do_test(13, mmu_test_13);
|
||||
do_test(14, mmu_test_14);
|
||||
do_test(15, mmu_test_15);
|
||||
do_test(16, mmu_test_16);
|
||||
do_test(17, mmu_test_17);
|
||||
|
||||
return fail;
|
||||
}
|
||||
|
||||
@@ -1,13 +1,27 @@
|
||||
SECTIONS
|
||||
{
|
||||
_start = .;
|
||||
. = 0;
|
||||
_start = .;
|
||||
.head : {
|
||||
KEEP(*(.head))
|
||||
}
|
||||
. = 0x1000;
|
||||
.text : { *(.text) }
|
||||
. = 0x3000;
|
||||
.data : { *(.data) }
|
||||
.bss : { *(.bss) }
|
||||
. = ALIGN(0x1000);
|
||||
.text : { *(.text) *(.text.*) *(.rodata) *(.rodata.*) }
|
||||
. = ALIGN(0x1000);
|
||||
.data : { *(.data) *(.data.*) *(.got) *(.toc) }
|
||||
. = ALIGN(0x80);
|
||||
__bss_start = .;
|
||||
.bss : {
|
||||
*(.dynsbss)
|
||||
*(.sbss)
|
||||
*(.scommon)
|
||||
*(.dynbss)
|
||||
*(.bss)
|
||||
*(.common)
|
||||
*(.bss.*)
|
||||
}
|
||||
. = ALIGN(0x80);
|
||||
__bss_end = .;
|
||||
. = . + 0x4000;
|
||||
__stack_top = .;
|
||||
}
|
||||
|
||||
Binary file not shown.
@@ -8,3 +8,10 @@ test 07:PASS
|
||||
test 08:PASS
|
||||
test 09:PASS
|
||||
test 10:PASS
|
||||
test 11:PASS
|
||||
test 12:PASS
|
||||
test 13:PASS
|
||||
test 14:PASS
|
||||
test 15:PASS
|
||||
test 16:PASS
|
||||
test 17:PASS
|
||||
|
||||
Reference in New Issue
Block a user