| # See LICENSE for license details. |
| |
| #***************************************************************************** |
| # dirty.S |
| #----------------------------------------------------------------------------- |
| # |
| # Test VM referenced and dirty bits. |
| # |
| |
| #include "riscv_test.h" |
| #include "test_macros.h" |
| |
| #if (DRAM_BASE >> 30 << 30) != DRAM_BASE |
| # error This test requires DRAM_BASE be SV39 superpage-aligned |
| #endif |
| |
| RVTEST_RV64M |
| RVTEST_CODE_BEGIN |
| |
| # Turn on VM |
| li a0, (SATP_MODE & ~(SATP_MODE<<1)) * SATP_MODE_SV39 |
| la a1, page_table_1 |
| srl a1, a1, RISCV_PGSHIFT |
| or a1, a1, a0 |
| csrw sptbr, a1 |
| sfence.vma |
| |
| # Set up MPRV with MPP=S, so loads and stores use S-mode |
| li a1, ((MSTATUS_MPP & ~(MSTATUS_MPP<<1)) * PRV_S) | MSTATUS_MPRV |
| csrs mstatus, a1 |
| |
| # Try a faulting store to make sure dirty bit is not set |
| li TESTNUM, 2 |
| li t2, 1 |
| sw t2, dummy - DRAM_BASE, a0 |
| |
| # Set SUM=1 so user memory access is permitted |
| li TESTNUM, 3 |
| li a1, ((MSTATUS_MPP & ~(MSTATUS_MPP<<1)) * PRV_S) | MSTATUS_SUM |
| csrs mstatus, a1 |
| |
| # Make sure SUM=1 works |
| lw t0, dummy - DRAM_BASE |
| bnez t0, die |
| |
| # Try a non-faulting store to make sure dirty bit is set |
| sw t2, dummy - DRAM_BASE, a0 |
| |
| # Make sure it succeeded |
| lw t0, dummy - DRAM_BASE |
| bne t0, t2, die |
| |
| # Leave MPRV |
| li t0, MSTATUS_MPRV |
| csrc mstatus, t0 |
| |
| # Make sure D bit is set |
| lw t0, page_table_1 |
| li a0, PTE_A | PTE_D |
| and t0, t0, a0 |
| bne t0, a0, die |
| |
| # Enter MPRV again |
| li t0, MSTATUS_MPRV |
| csrs mstatus, t0 |
| |
| # Make sure that superpage entries trap when PPN LSBs are set. |
| li TESTNUM, 4 |
| lw a0, page_table_1 - DRAM_BASE |
| or a0, a0, 1 << PTE_PPN_SHIFT |
| sw a0, page_table_1 - DRAM_BASE, t0 |
| sfence.vma |
| sw a0, page_table_1 - DRAM_BASE, t0 |
| j die |
| |
| RVTEST_PASS |
| |
| TEST_PASSFAIL |
| |
| .align 2 |
| .global mtvec_handler |
| mtvec_handler: |
| csrr t0, mcause |
| add t0, t0, -CAUSE_STORE_PAGE_FAULT |
| bnez t0, die |
| |
| li t1, 2 |
| bne TESTNUM, t1, 1f |
| # Make sure D bit is clear |
| lw t0, page_table_1 |
| and t1, t0, PTE_D |
| bnez t1, die |
| skip: |
| csrr t0, mepc |
| add t0, t0, 4 |
| csrw mepc, t0 |
| mret |
| |
| 1: |
| li t1, 3 |
| bne TESTNUM, t1, 1f |
| # The implementation doesn't appear to set D bits in HW. |
| # Make sure the D bit really is clear. |
| lw t0, page_table_1 |
| and t1, t0, PTE_D |
| bnez t1, die |
| # Set the D bit. |
| or t0, t0, PTE_D |
| sw t0, page_table_1, t1 |
| sfence.vma |
| mret |
| |
| 1: |
| li t1, 4 |
| bne TESTNUM, t1, 1f |
| j pass |
| |
| 1: |
| die: |
| RVTEST_FAIL |
| |
| RVTEST_CODE_END |
| |
| .data |
| RVTEST_DATA_BEGIN |
| |
| TEST_DATA |
| |
| .align 12 |
| page_table_1: .dword (DRAM_BASE/RISCV_PGSIZE << PTE_PPN_SHIFT) | PTE_V | PTE_U | PTE_R | PTE_W | PTE_X | PTE_A |
| dummy: .dword 0 |
| |
| RVTEST_DATA_END |