| #include "macros.inc" |
| |
| test_suite mmu |
| |
| #if XCHAL_HAVE_PTP_MMU |
| #define BASE 0x20000000 |
| #define TLB_BASE 0x80000000 |
| |
| .purgem test_init |
| |
| .macro clean_tlb_way way, page_size, n_entries |
| movi a2, \way |
| movi a3, \page_size |
| movi a4, \n_entries |
| loop a4, 1f |
| idtlb a2 |
| iitlb a2 |
| add a2, a2, a3 |
| 1: |
| .endm |
| |
| .macro test_init |
| clean_tlb_way 0, 0x00001000, 4 |
| clean_tlb_way 1, 0x00001000, 4 |
| clean_tlb_way 2, 0x00001000, 4 |
| clean_tlb_way 3, 0x00001000, 4 |
| clean_tlb_way 4, 0x00100000, 4 |
| movi a2, 0x00000007 |
| idtlb a2 |
| movi a2, 0x00000008 |
| idtlb a2 |
| movi a2, 0x00000009 |
| idtlb a2 |
| #if XCHAL_HAVE_SPANNING_WAY |
| movi a2, BASE | XCHAL_SPANNING_WAY |
| idtlb a2 |
| iitlb a2 |
| movi a2, TLB_BASE | XCHAL_SPANNING_WAY |
| idtlb a2 |
| iitlb a2 |
| movi a2, TLB_BASE |
| wsr a2, ptevaddr |
| #endif |
| .endm |
| |
| test tlb_group |
| movi a2, 0x04000002 /* PPN */ |
| movi a3, BASE + 0x01200004 /* VPN */ |
| wdtlb a2, a3 |
| witlb a2, a3 |
| movi a3, 0x00200004 |
| rdtlb0 a1, a3 |
| ritlb0 a2, a3 |
| movi a3, BASE + 0x01000001 |
| assert eq, a1, a3 |
| assert eq, a2, a3 |
| movi a3, 0x00200004 |
| rdtlb1 a1, a3 |
| ritlb1 a2, a3 |
| movi a3, 0x04000002 |
| assert eq, a1, a3 |
| assert eq, a2, a3 |
| movi a3, BASE + 0x01234567 |
| pdtlb a1, a3 |
| pitlb a2, a3 |
| movi a3, BASE + 0x01234014 |
| assert eq, a1, a3 |
| movi a3, BASE + 0x0123400c |
| assert eq, a2, a3 |
| movi a3, 0x00200004 |
| idtlb a3 |
| iitlb a3 |
| movi a3, BASE + 0x01234567 |
| pdtlb a1, a3 |
| pitlb a2, a3 |
| movi a3, 0x00000010 |
| and a1, a1, a3 |
| assert eqi, a1, 0 |
| movi a3, 0x00000008 |
| and a2, a2, a3 |
| assert eqi, a2, 0 |
| test_end |
| |
| test itlb_miss |
| set_vector kernel, 1f |
| |
| movi a3, BASE + 0x00100000 |
| jx a3 |
| test_fail |
| 1: |
| rsr a2, excvaddr |
| assert eq, a2, a3 |
| rsr a2, exccause |
| movi a3, 16 |
| assert eq, a2, a3 |
| test_end |
| |
| test dtlb_miss |
| set_vector kernel, 1f |
| |
| movi a3, BASE + 0x00100000 |
| l8ui a2, a3, 0 |
| test_fail |
| 1: |
| rsr a2, excvaddr |
| assert eq, a2, a3 |
| rsr a2, exccause |
| movi a3, 24 |
| assert eq, a2, a3 |
| test_end |
| |
| test itlb_multi_hit |
| set_vector kernel, 1f |
| |
| movi a2, 0x04000002 /* PPN */ |
| movi a3, 0xf0000004 /* VPN */ |
| witlb a2, a3 |
| movi a3, 0xf0000000 |
| pitlb a2, a3 |
| test_fail |
| 1: |
| rsr a2, exccause |
| movi a3, 17 |
| assert eq, a2, a3 |
| test_end |
| |
| test dtlb_multi_hit |
| set_vector kernel, 1f |
| |
| movi a2, 0x04000002 /* PPN */ |
| movi a3, BASE + 0x01200004 /* VPN */ |
| wdtlb a2, a3 |
| movi a3, BASE + 0x01200007 /* VPN */ |
| wdtlb a2, a3 |
| movi a3, BASE + 0x01200000 |
| pdtlb a2, a3 |
| test_fail |
| 1: |
| rsr a2, exccause |
| movi a3, 25 |
| assert eq, a2, a3 |
| test_end |
| |
| test inst_fetch_privilege |
| set_vector kernel, 3f |
| |
| movi a2, 0x4004f |
| wsr a2, ps |
| 1: |
| isync |
| nop |
| 2: |
| test_fail |
| 3: |
| movi a1, 1b |
| rsr a2, excvaddr |
| rsr a3, epc1 |
| assert ge, a2, a1 |
| assert ge, a3, a1 |
| movi a1, 2b |
| assert lt, a2, a1 |
| assert lt, a3, a1 |
| rsr a2, exccause |
| movi a3, 18 |
| assert eq, a2, a3 |
| rsr a2, ps |
| movi a3, 0x4005f |
| assert eq, a2, a3 |
| test_end |
| |
| test load_store_privilege |
| set_vector kernel, 2f |
| |
| movi a3, 10f |
| pitlb a3, a3 |
| ritlb1 a2, a3 |
| movi a1, 0x10 |
| or a2, a2, a1 |
| movi a1, 0x000ff000 |
| and a3, a3, a1 |
| movi a1, 4 |
| or a3, a3, a1 |
| movi a5, BASE |
| add a3, a3, a5 |
| witlb a2, a3 |
| movi a3, 10f |
| movi a1, 0x000fffff |
| and a1, a3, a1 |
| add a1, a1, a5 |
| |
| movi a2, 0x04000003 /* PPN */ |
| movi a3, BASE + 0x01200004 /* VPN */ |
| wdtlb a2, a3 |
| movi a3, BASE + 0x01200001 |
| movi a2, 0x4004f |
| jx a1 |
| 10: |
| wsr a2, ps |
| isync |
| 1: |
| l8ui a2, a3, 0 |
| test_fail |
| 2: |
| rsr a2, excvaddr |
| assert eq, a2, a3 |
| rsr a2, epc1 |
| movi a3, 1b |
| movi a1, 0x000fffff |
| and a3, a3, a1 |
| add a3, a3, a5 |
| assert eq, a2, a3 |
| rsr a2, exccause |
| movi a3, 26 |
| assert eq, a2, a3 |
| rsr a2, ps |
| movi a3, 0x4005f |
| assert eq, a2, a3 |
| test_end |
| |
| test cring_load_store_privilege |
| set_vector kernel, 0 |
| set_vector double, 2f |
| |
| movi a2, 0x04000003 /* PPN */ |
| movi a3, BASE + 0x01200004 /* VPN */ |
| wdtlb a2, a3 |
| movi a3, BASE + 0x01200004 |
| movi a2, 0x4005f /* ring 1 + excm => cring == 0 */ |
| wsr a2, ps |
| isync |
| l8ui a2, a3, 0 /* cring used */ |
| 1: |
| l32e a2, a3, -4 /* ring used */ |
| test_fail |
| 2: |
| rsr a2, excvaddr |
| addi a2, a2, 4 |
| assert eq, a2, a3 |
| rsr a2, depc |
| movi a3, 1b |
| assert eq, a2, a3 |
| rsr a2, exccause |
| movi a3, 26 |
| assert eq, a2, a3 |
| rsr a2, ps |
| movi a3, 0x4005f |
| assert eq, a2, a3 |
| test_end |
| |
| test inst_fetch_prohibited |
| set_vector kernel, 2f |
| |
| movi a3, 10f |
| pitlb a3, a3 |
| ritlb1 a2, a3 |
| movi a1, 0xfffff000 |
| and a2, a2, a1 |
| movi a1, 0x4 |
| or a2, a2, a1 |
| movi a1, 0x000ff000 |
| and a3, a3, a1 |
| movi a1, 4 |
| or a3, a3, a1 |
| movi a5, BASE |
| add a3, a3, a5 |
| witlb a2, a3 |
| movi a3, 10f |
| movi a1, 0x000fffff |
| and a1, a3, a1 |
| add a1, a1, a5 |
| jx a1 |
| .align 4 |
| 10: |
| nop |
| test_fail |
| 2: |
| rsr a2, excvaddr |
| assert eq, a2, a1 |
| rsr a2, epc1 |
| assert eq, a2, a1 |
| rsr a2, exccause |
| movi a3, 20 |
| assert eq, a2, a3 |
| test_end |
| |
| test load_prohibited |
| set_vector kernel, 2f |
| |
| movi a2, 0x0400000c /* PPN */ |
| movi a3, BASE + 0x01200004 /* VPN */ |
| wdtlb a2, a3 |
| movi a3, BASE + 0x01200002 |
| 1: |
| l8ui a2, a3, 0 |
| test_fail |
| 2: |
| rsr a2, excvaddr |
| assert eq, a2, a3 |
| rsr a2, epc1 |
| movi a3, 1b |
| assert eq, a2, a3 |
| rsr a2, exccause |
| movi a3, 28 |
| assert eq, a2, a3 |
| test_end |
| |
| test store_prohibited |
| set_vector kernel, 2f |
| |
| movi a2, 0x04000001 /* PPN */ |
| movi a3, BASE + 0x01200004 /* VPN */ |
| wdtlb a2, a3 |
| movi a3, BASE + 0x01200003 |
| l8ui a2, a3, 0 |
| 1: |
| s8i a2, a3, 0 |
| test_fail |
| 2: |
| rsr a2, excvaddr |
| assert eq, a2, a3 |
| rsr a2, epc1 |
| movi a3, 1b |
| assert eq, a2, a3 |
| rsr a2, exccause |
| movi a3, 29 |
| assert eq, a2, a3 |
| test_end |
| |
| /* Set up page table entry vaddr->paddr, ring=pte_ring, attr=pte_attr |
| * and DTLB way 7 to cover this PTE, ring=pt_ring, attr=pt_attr |
| */ |
| .macro pt_setup pt_ring, pt_attr, pte_ring, vaddr, paddr, pte_attr |
| movi a2, TLB_BASE |
| wsr a2, ptevaddr |
| |
| movi a3, TLB_BASE | 7 | (((\vaddr) >> 10) & 0xfffff000) /* way 7 */ |
| movi a4, 0x04000003 | ((\pt_ring) << 4) /* PADDR 64M */ |
| wdtlb a4, a3 |
| isync |
| |
| movi a3, ((\paddr) & 0xfffff000) | ((\pte_ring) << 4) | (\pte_attr) |
| movi a1, ((\vaddr) >> 12) << 2 |
| add a2, a1, a2 |
| s32i a3, a2, 0 |
| |
| movi a3, TLB_BASE | 7 | (((\vaddr) >> 10) & 0xfffff000) /* way 7 */ |
| movi a4, 0x04000000 | ((\pt_ring) << 4) | (\pt_attr) /* PADDR 64M */ |
| wdtlb a4, a3 |
| isync |
| |
| movi a3, (\vaddr) |
| .endm |
| |
| /* out: PS.RING=ring, PS.EXCM=excm, a3=vaddr */ |
| .macro go_ring ring, excm, vaddr |
| movi a3, 10f |
| pitlb a3, a3 |
| ritlb1 a2, a3 |
| movi a1, 0x10 |
| or a2, a2, a1 |
| movi a1, 0x000ff000 |
| and a3, a3, a1 |
| movi a1, 4 |
| or a3, a3, a1 |
| movi a5, BASE |
| add a3, a3, a5 |
| witlb a2, a3 |
| movi a3, 10f |
| movi a1, 0x000fffff |
| and a1, a3, a1 |
| add a1, a1, a5 |
| |
| movi a2, 0 |
| wsr a2, excvaddr |
| |
| movi a3, \vaddr |
| movi a2, 0x4000f | ((\ring) << 6) | ((\excm) << 4) |
| jx a1 |
| 10: |
| wsr a2, ps |
| isync |
| .endm |
| |
| /* in: a3 -- virtual address to test */ |
| .macro assert_auto_tlb |
| movi a2, 0x4000f |
| wsr a2, ps |
| isync |
| pdtlb a2, a3 |
| movi a1, 0xfffff01f |
| and a2, a2, a1 |
| movi a1, 0xfffff000 |
| and a1, a1, a3 |
| xor a1, a1, a2 |
| assert gei, a1, 0x10 |
| movi a2, 0x14 |
| assert lt, a1, a2 |
| .endm |
| |
| /* in: a3 -- virtual address to test */ |
| .macro assert_no_auto_tlb |
| movi a2, 0x4000f |
| wsr a2, ps |
| isync |
| pdtlb a2, a3 |
| movi a1, 0x10 |
| and a1, a1, a2 |
| assert eqi, a1, 0 |
| .endm |
| |
| .macro assert_sr sr, v |
| rsr a2, \sr |
| movi a1, (\v) |
| assert eq, a1, a2 |
| .endm |
| |
| .macro assert_epc1_1m vaddr |
| movi a2, (\vaddr) |
| movi a1, 0xfffff |
| and a1, a1, a2 |
| movi a5, BASE |
| add a1, a1, a5 |
| rsr a2, epc1 |
| assert eq, a1, a2 |
| .endm |
| |
| test dtlb_autoload |
| set_vector kernel, 0 |
| |
| pt_setup 0, 3, 1, BASE + 0x1000, 0x1000, 3 |
| assert_no_auto_tlb |
| |
| l8ui a1, a3, 0 |
| |
| rsr a2, excvaddr |
| assert eq, a2, a3 |
| |
| assert_auto_tlb |
| test_end |
| |
| test autoload_load_store_privilege |
| set_vector kernel, 0 |
| set_vector double, 2f |
| |
| pt_setup 0, 3, 0, BASE + 0x2000, 0x2000, 3 |
| movi a3, BASE + 0x2004 |
| assert_no_auto_tlb |
| |
| movi a2, 0x4005f /* ring 1 + excm => cring == 0 */ |
| wsr a2, ps |
| isync |
| 1: |
| l32e a2, a3, -4 /* ring used */ |
| test_fail |
| 2: |
| rsr a2, excvaddr |
| addi a1, a3, -4 |
| assert eq, a1, a2 |
| |
| assert_auto_tlb |
| assert_sr depc, 1b |
| assert_sr exccause, 26 |
| test_end |
| |
| test autoload_pte_load_prohibited |
| set_vector kernel, 2f |
| |
| pt_setup 0, 3, 0, BASE + 0x3000, 0, 0xc |
| assert_no_auto_tlb |
| 1: |
| l32i a2, a3, 0 |
| test_fail |
| 2: |
| rsr a2, excvaddr |
| assert eq, a2, a3 |
| |
| assert_auto_tlb |
| assert_sr epc1, 1b |
| assert_sr exccause, 28 |
| test_end |
| |
| test autoload_pt_load_prohibited |
| set_vector kernel, 2f |
| |
| pt_setup 0, 0xc, 0, BASE + 0x4000, 0x4000, 3 |
| assert_no_auto_tlb |
| 1: |
| l32i a2, a3, 0 |
| test_fail |
| 2: |
| rsr a2, excvaddr |
| assert eq, a2, a3 |
| |
| assert_no_auto_tlb |
| assert_sr epc1, 1b |
| assert_sr exccause, 24 |
| test_end |
| |
| test autoload_pt_privilege |
| set_vector kernel, 2f |
| pt_setup 0, 3, 1, BASE + 0x5000, 0, 3 |
| go_ring 1, 0, BASE + 0x5001 |
| |
| l8ui a2, a3, 0 |
| 1: |
| syscall |
| 2: |
| rsr a2, excvaddr |
| assert eq, a2, a3 |
| |
| assert_auto_tlb |
| assert_epc1_1m 1b |
| assert_sr exccause, 1 |
| test_end |
| |
| test autoload_pte_privilege |
| set_vector kernel, 2f |
| pt_setup 0, 3, 0, BASE + 0x6000, 0, 3 |
| go_ring 1, 0, BASE + 0x6001 |
| 1: |
| l8ui a2, a3, 0 |
| syscall |
| 2: |
| rsr a2, excvaddr |
| assert eq, a2, a3 |
| |
| assert_auto_tlb |
| assert_epc1_1m 1b |
| assert_sr exccause, 26 |
| test_end |
| |
| test autoload_3_level_pt |
| set_vector kernel, 2f |
| pt_setup 1, 3, 1, BASE + 0x00400000, 0, 3 |
| pt_setup 1, 3, 1, TLB_BASE + ((BASE + 0x00400000) >> 10), 0x2000000, 3 |
| go_ring 1, 0, BASE + 0x00400001 |
| 1: |
| l8ui a2, a3, 0 |
| syscall |
| 2: |
| rsr a2, excvaddr |
| assert eq, a2, a3 |
| |
| assert_no_auto_tlb |
| assert_epc1_1m 1b |
| assert_sr exccause, 24 |
| test_end |
| |
| test cross_page_insn |
| set_vector kernel, 2f |
| |
| movi a2, 0x04000003 /* PPN */ |
| movi a3, BASE + 0x00007000 /* VPN */ |
| witlb a2, a3 |
| wdtlb a2, a3 |
| movi a3, BASE + 0x00008000 /* VPN */ |
| witlb a2, a3 |
| wdtlb a2, a3 |
| |
| movi a2, BASE + 0x00007fff |
| movi a3, 20f |
| movi a4, 21f |
| sub a4, a4, a3 |
| loop a4, 1f |
| l8ui a5, a3, 0 |
| s8i a5, a2, 0 |
| addi a2, a2, 1 |
| addi a3, a3, 1 |
| 1: |
| movi a2, BASE + 0x00007fff |
| movi a3, BASE + 0x00008000 |
| /* DTLB: OK, ITLB: OK */ |
| jx a2 |
| |
| .begin no-transform |
| 20: |
| l32i a2, a3, 0 |
| syscall |
| 21: |
| .end no-transform |
| |
| 2: |
| rsr a2, exccause |
| movi a3, 1 |
| assert eq, a2, a3 |
| rsr a2, epc1 |
| movi a3, BASE + 0x8002 |
| assert eq, a2, a3 |
| rsr a2, excsave1 |
| movi a3, BASE + 0x00007fff |
| assert ne, a2, a3 |
| |
| reset_ps |
| set_vector kernel, 3f |
| |
| movi a2, 0x0400000c /* PPN */ |
| movi a3, BASE + 0x00008000 /* VPN */ |
| wdtlb a2, a3 |
| movi a2, BASE + 0x00007fff |
| movi a3, BASE + 0x00008000 |
| /* DTLB: FAIL, ITLB: OK */ |
| jx a2 |
| 3: |
| rsr a2, exccause |
| movi a3, 28 |
| assert eq, a2, a3 |
| rsr a2, epc1 |
| movi a3, BASE + 0x7fff |
| assert eq, a2, a3 |
| rsr a2, excsave1 |
| movi a3, BASE + 0x00007fff |
| assert eq, a2, a3 |
| |
| reset_ps |
| set_vector kernel, 4f |
| |
| movi a2, 0x0400000c /* PPN */ |
| movi a3, BASE + 0x00008000 /* VPN */ |
| witlb a2, a3 |
| movi a2, 0x04000003 /* PPN */ |
| wdtlb a2, a3 |
| movi a2, BASE + 0x00007fff |
| movi a3, BASE + 0x00008000 |
| /* DTLB: OK, ITLB: FAIL */ |
| jx a2 |
| 4: |
| rsr a2, exccause |
| movi a3, 20 |
| assert eq, a2, a3 |
| rsr a2, epc1 |
| movi a3, BASE + 0x7fff |
| assert eq, a2, a3 |
| rsr a2, excsave1 |
| movi a3, BASE + 0x00007fff |
| assert eq, a2, a3 |
| |
| reset_ps |
| set_vector kernel, 5f |
| |
| movi a2, 0x0400000c /* PPN */ |
| movi a3, BASE + 0x00008000 /* VPN */ |
| wdtlb a2, a3 |
| movi a2, BASE + 0x00007fff |
| movi a3, BASE + 0x00008000 |
| /* DTLB: FAIL, ITLB: FAIL */ |
| jx a2 |
| 5: |
| rsr a2, exccause |
| movi a3, 20 |
| assert eq, a2, a3 |
| rsr a2, epc1 |
| movi a3, BASE + 0x7fff |
| assert eq, a2, a3 |
| rsr a2, excsave1 |
| movi a3, BASE + 0x00007fff |
| assert eq, a2, a3 |
| test_end |
| |
| test cross_page_tb |
| set_vector kernel, 2f |
| |
| movi a2, 0x04000003 /* PPN */ |
| movi a3, BASE + 0x00007000 /* VPN */ |
| witlb a2, a3 |
| wdtlb a2, a3 |
| movi a3, BASE + 0x00008000 /* VPN */ |
| witlb a2, a3 |
| wdtlb a2, a3 |
| |
| movi a2, BASE + 0x00007ffc |
| movi a3, 20f |
| movi a4, 21f |
| sub a4, a4, a3 |
| loop a4, 1f |
| l8ui a5, a3, 0 |
| s8i a5, a2, 0 |
| addi a2, a2, 1 |
| addi a3, a3, 1 |
| 1: |
| movi a2, BASE + 0x00007ffc |
| movi a3, BASE + 0x00008000 |
| /* DTLB: OK, ITLB: OK */ |
| jx a2 |
| |
| .begin no-transform |
| 20: |
| l32i a2, a3, 0 |
| syscall |
| 21: |
| .end no-transform |
| |
| 2: |
| rsr a2, exccause |
| movi a3, 1 |
| assert eq, a2, a3 |
| rsr a2, epc1 |
| movi a3, BASE + 0x7fff |
| assert eq, a2, a3 |
| rsr a2, excsave1 |
| movi a3, BASE + 0x00007ffc |
| assert ne, a2, a3 |
| |
| reset_ps |
| set_vector kernel, 3f |
| |
| movi a2, 0x0400000c /* PPN */ |
| movi a3, BASE + 0x00008000 /* VPN */ |
| wdtlb a2, a3 |
| movi a2, BASE + 0x00007ffc |
| movi a3, BASE + 0x00008000 |
| /* DTLB: FAIL, ITLB: OK */ |
| jx a2 |
| 3: |
| rsr a2, exccause |
| movi a3, 28 |
| assert eq, a2, a3 |
| rsr a2, epc1 |
| movi a3, BASE + 0x7ffc |
| assert eq, a2, a3 |
| rsr a2, excsave1 |
| movi a3, BASE + 0x00007ffc |
| assert eq, a2, a3 |
| |
| reset_ps |
| set_vector kernel, 4f |
| |
| movi a2, 0x0400000c /* PPN */ |
| movi a3, BASE + 0x00008000 /* VPN */ |
| witlb a2, a3 |
| movi a2, 0x04000003 /* PPN */ |
| wdtlb a2, a3 |
| movi a2, BASE + 0x00007ffc |
| movi a3, BASE + 0x00008000 |
| /* DTLB: OK, ITLB: FAIL */ |
| jx a2 |
| 4: |
| rsr a2, exccause |
| movi a3, 20 |
| assert eq, a2, a3 |
| rsr a2, epc1 |
| movi a3, BASE + 0x7fff |
| assert eq, a2, a3 |
| rsr a2, excsave1 |
| movi a3, BASE + 0x00007ffc |
| assert ne, a2, a3 |
| |
| reset_ps |
| set_vector kernel, 5f |
| |
| movi a2, 0x0400000c /* PPN */ |
| movi a3, BASE + 0x00008000 /* VPN */ |
| wdtlb a2, a3 |
| movi a2, BASE + 0x00007ffc |
| movi a3, BASE + 0x00008000 |
| /* DTLB: FAIL, ITLB: FAIL */ |
| jx a2 |
| 5: |
| rsr a2, exccause |
| movi a3, 28 |
| assert eq, a2, a3 |
| rsr a2, epc1 |
| movi a3, BASE + 0x7ffc |
| assert eq, a2, a3 |
| rsr a2, excsave1 |
| movi a3, BASE + 0x00007ffc |
| assert eq, a2, a3 |
| test_end |
| |
| #endif |
| |
| test_suite_end |