1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21#include "qemu/osdep.h"
22#include "cpu.h"
23#include "cpu_bits.h"
24#include "monitor/monitor.h"
25#include "monitor/hmp-target.h"
26
27#ifdef TARGET_RISCV64
28#define PTE_HEADER_FIELDS "vaddr paddr "\
29 "size attr\n"
30#define PTE_HEADER_DELIMITER "---------------- ---------------- "\
31 "---------------- -------\n"
32#else
33#define PTE_HEADER_FIELDS "vaddr paddr size attr\n"
34#define PTE_HEADER_DELIMITER "-------- ---------------- -------- -------\n"
35#endif
36
37
38static target_ulong addr_canonical(int va_bits, target_ulong addr)
39{
40#ifdef TARGET_RISCV64
41 if (addr & (1UL << (va_bits - 1))) {
42 addr |= (hwaddr)-(1L << va_bits);
43 }
44#endif
45
46 return addr;
47}
48
49static void print_pte_header(Monitor *mon)
50{
51 monitor_printf(mon, PTE_HEADER_FIELDS);
52 monitor_printf(mon, PTE_HEADER_DELIMITER);
53}
54
55static void print_pte(Monitor *mon, int va_bits, target_ulong vaddr,
56 hwaddr paddr, target_ulong size, int attr)
57{
58
59 if (vaddr >= (1UL << va_bits)) {
60 return;
61 }
62
63 if (!size) {
64 return;
65 }
66
67 monitor_printf(mon, TARGET_FMT_lx " " TARGET_FMT_plx " " TARGET_FMT_lx
68 " %c%c%c%c%c%c%c\n",
69 addr_canonical(va_bits, vaddr),
70 paddr, size,
71 attr & PTE_R ? 'r' : '-',
72 attr & PTE_W ? 'w' : '-',
73 attr & PTE_X ? 'x' : '-',
74 attr & PTE_U ? 'u' : '-',
75 attr & PTE_G ? 'g' : '-',
76 attr & PTE_A ? 'a' : '-',
77 attr & PTE_D ? 'd' : '-');
78}
79
80static void walk_pte(Monitor *mon, hwaddr base, target_ulong start,
81 int level, int ptidxbits, int ptesize, int va_bits,
82 target_ulong *vbase, hwaddr *pbase, hwaddr *last_paddr,
83 target_ulong *last_size, int *last_attr)
84{
85 hwaddr pte_addr;
86 hwaddr paddr;
87 target_ulong pgsize;
88 target_ulong pte;
89 int ptshift;
90 int attr;
91 int idx;
92
93 if (level < 0) {
94 return;
95 }
96
97 ptshift = level * ptidxbits;
98 pgsize = 1UL << (PGSHIFT + ptshift);
99
100 for (idx = 0; idx < (1UL << ptidxbits); idx++) {
101 pte_addr = base + idx * ptesize;
102 cpu_physical_memory_read(pte_addr, &pte, ptesize);
103
104 paddr = (hwaddr)(pte >> PTE_PPN_SHIFT) << PGSHIFT;
105 attr = pte & 0xff;
106
107
108 if (attr & PTE_V) {
109 if (attr & (PTE_R | PTE_W | PTE_X)) {
110
111
112
113
114
115
116
117
118 if ((*last_attr != attr) ||
119 (*last_paddr + *last_size != paddr)) {
120 print_pte(mon, va_bits, *vbase, *pbase,
121 *last_paddr + *last_size - *pbase, *last_attr);
122
123 *vbase = start;
124 *pbase = paddr;
125 *last_attr = attr;
126 }
127
128 *last_paddr = paddr;
129 *last_size = pgsize;
130 } else {
131
132 walk_pte(mon, paddr, start, level - 1, ptidxbits, ptesize,
133 va_bits, vbase, pbase, last_paddr,
134 last_size, last_attr);
135 }
136 }
137
138 start += pgsize;
139 }
140
141}
142
143static void mem_info_svxx(Monitor *mon, CPUArchState *env)
144{
145 int levels, ptidxbits, ptesize, vm, va_bits;
146 hwaddr base;
147 target_ulong vbase;
148 hwaddr pbase;
149 hwaddr last_paddr;
150 target_ulong last_size;
151 int last_attr;
152
153 if (riscv_cpu_mxl(env) == MXL_RV32) {
154 base = (hwaddr)get_field(env->satp, SATP32_PPN) << PGSHIFT;
155 vm = get_field(env->satp, SATP32_MODE);
156 } else {
157 base = (hwaddr)get_field(env->satp, SATP64_PPN) << PGSHIFT;
158 vm = get_field(env->satp, SATP64_MODE);
159 }
160
161 switch (vm) {
162 case VM_1_10_SV32:
163 levels = 2;
164 ptidxbits = 10;
165 ptesize = 4;
166 break;
167 case VM_1_10_SV39:
168 levels = 3;
169 ptidxbits = 9;
170 ptesize = 8;
171 break;
172 case VM_1_10_SV48:
173 levels = 4;
174 ptidxbits = 9;
175 ptesize = 8;
176 break;
177 case VM_1_10_SV57:
178 levels = 5;
179 ptidxbits = 9;
180 ptesize = 8;
181 break;
182 default:
183 g_assert_not_reached();
184 break;
185 }
186
187
188 va_bits = PGSHIFT + levels * ptidxbits;
189
190
191 print_pte_header(mon);
192
193 vbase = -1;
194 pbase = -1;
195 last_paddr = -1;
196 last_size = 0;
197 last_attr = 0;
198
199
200 walk_pte(mon, base, 0, levels - 1, ptidxbits, ptesize, va_bits,
201 &vbase, &pbase, &last_paddr, &last_size, &last_attr);
202
203
204 print_pte(mon, va_bits, vbase, pbase,
205 last_paddr + last_size - pbase, last_attr);
206}
207
208void hmp_info_mem(Monitor *mon, const QDict *qdict)
209{
210 CPUArchState *env;
211
212 env = mon_get_cpu_env(mon);
213 if (!env) {
214 monitor_printf(mon, "No CPU available\n");
215 return;
216 }
217
218 if (!riscv_feature(env, RISCV_FEATURE_MMU)) {
219 monitor_printf(mon, "S-mode MMU unavailable\n");
220 return;
221 }
222
223 if (riscv_cpu_mxl(env) == MXL_RV32) {
224 if (!(env->satp & SATP32_MODE)) {
225 monitor_printf(mon, "No translation or protection\n");
226 return;
227 }
228 } else {
229 if (!(env->satp & SATP64_MODE)) {
230 monitor_printf(mon, "No translation or protection\n");
231 return;
232 }
233 }
234
235 mem_info_svxx(mon, env);
236}
237