1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
|
# 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
|