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
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
|
# See LICENSE for license details.
#*****************************************************************************
# napot.S
#-----------------------------------------------------------------------------
#
# Test Svnapot
#
#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
#if __riscv_xlen != 64
# error This test requires RV64
#endif
RVTEST_RV64M
RVTEST_CODE_BEGIN
# Construct the page table
#define MY_VA 0x40201010
# VPN 2 == VPN 1 == VPN 0 == 0x1
# Page offset == 0x10
####
# Level 0 PTE contents
# PPN
la a0, my_data
srl a0, a0, 12
# adjust the PPN to be in NAPOT form
li a1, ~0xF
and a0, a0, a1
ori a0, a0, 0x8
# attributes
sll a0, a0, PTE_PPN_SHIFT
li a1, PTE_V | PTE_U | PTE_R | PTE_W | PTE_X | PTE_A | PTE_D | PTE_N
or a0, a0, a1
# Level 0 PTE address
la a1, page_table
addi a1, a1, ((MY_VA >> 12) & 0x1FF) * 8
# Level 0 PTE store
sd a0, (a1)
####
# Level 1 PTE contents
la a0, page_table
srl a0, a0, 12
sll a0, a0, PTE_PPN_SHIFT
li a1, PTE_V | PTE_U
or a0, a0, a1
# Level 1 PTE address
la a1, page_table
addi a1, a1, ((MY_VA >> 21) & 0x1FF) * 8
li a2, 1 << 12
add a1, a1, a2
# Level 1 PTE store
sd a0, (a1)
####
# Level 2 PTE contents
la a0, page_table
li a1, 1 << 12
add a0, a0, a1
srl a0, a0, 12
sll a0, a0, PTE_PPN_SHIFT
li a1, PTE_V | PTE_U
or a0, a0, a1
# Level 2 PTE address
la a1, page_table
addi a1, a1, ((MY_VA >> 30) & 0x1FF) * 8
li a2, 2 << 12
add a1, a1, a2
# Level 2 PTE store
sd a0, (a1)
####
# Do a load from the PA that would be written if the PTE were misinterpreted as non-NAPOT
la a0, my_data
li a1, ~0xFFFF
and a0, a0, a1
li a1, 0x8000 | (MY_VA & 0xFFF)
or a3, a0, a1
li a1, 0
sw a1, (a3)
####
li TESTNUM, 1
## Turn on VM
la a1, page_table
li a2, 2 << 12
add a1, a1, a2
srl a1, a1, 12
li a0, (SATP_MODE & ~(SATP_MODE<<1)) * SATP_MODE_SV39
or a0, a0, a1
csrw satp, a0
sfence.vma
# Set up MPRV with MPP=S and SUM=1, so loads and stores use S-mode and S can access U pages
li a1, ((MSTATUS_MPP & ~(MSTATUS_MPP<<1)) * PRV_S) | MSTATUS_MPRV | MSTATUS_SUM
csrs mstatus, a1
# Do a store to MY_VA
li a0, MY_VA
li a1, 42
sw a1, (a0)
# Clear MPRV
li a1, MSTATUS_MPRV
csrc mstatus, a1
# Do a load from the PA that would be written if the PTE were misinterpreted as non-NAPOT
lw a1, (a3)
# Check the result
li a0, 42
beq a1, a0, die
# Do a load from the PA for MY_VA
la a0, my_data
li a1, MY_VA & 0xFFFF
add a0, a0, a1
lw a1, (a0)
li a2, 42
# Check the result
bne a1, a2, die
####
RVTEST_PASS
TEST_PASSFAIL
.align 2
.global mtvec_handler
mtvec_handler:
die:
RVTEST_FAIL
RVTEST_CODE_END
.data
RVTEST_DATA_BEGIN
TEST_DATA
.align 20
page_table: .dword 0
.align 20
my_data: .dword 0
RVTEST_DATA_END
|