2 * QEMU monitor for RISC-V
4 * Copyright (c) 2019 Bin Meng <bmeng.cn@gmail.com>
6 * RISC-V specific monitor commands implementation
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms and conditions of the GNU General Public License,
10 * version 2 or later, as published by the Free Software Foundation.
12 * This program is distributed in the hope it will be useful, but WITHOUT
13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
17 * You should have received a copy of the GNU General Public License along with
18 * this program. If not, see <http://www.gnu.org/licenses/>.
21 #include "qemu/osdep.h"
24 #include "monitor/monitor.h"
25 #include "monitor/hmp-target.h"
28 #define PTE_HEADER_FIELDS "vaddr paddr "\
30 #define PTE_HEADER_DELIMITER "---------------- ---------------- "\
31 "---------------- -------\n"
33 #define PTE_HEADER_FIELDS "vaddr paddr size attr\n"
34 #define PTE_HEADER_DELIMITER "-------- ---------------- -------- -------\n"
37 /* Perform linear address sign extension */
38 static target_ulong
addr_canonical(int va_bits
, target_ulong addr
)
41 if (addr
& (1UL << (va_bits
- 1))) {
42 addr
|= (hwaddr
)-(1L << va_bits
);
49 static void print_pte_header(Monitor
*mon
)
51 monitor_printf(mon
, PTE_HEADER_FIELDS
);
52 monitor_printf(mon
, PTE_HEADER_DELIMITER
);
55 static void print_pte(Monitor
*mon
, int va_bits
, target_ulong vaddr
,
56 hwaddr paddr
, target_ulong size
, int attr
)
58 /* santity check on vaddr */
59 if (vaddr
>= (1UL << va_bits
)) {
67 monitor_printf(mon
, TARGET_FMT_lx
" " TARGET_FMT_plx
" " TARGET_FMT_lx
69 addr_canonical(va_bits
, vaddr
),
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' : '-');
80 static 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
)
97 ptshift
= level
* ptidxbits
;
98 pgsize
= 1UL << (PGSHIFT
+ ptshift
);
100 for (idx
= 0; idx
< (1UL << ptidxbits
); idx
++) {
101 pte_addr
= base
+ idx
* ptesize
;
102 cpu_physical_memory_read(pte_addr
, &pte
, ptesize
);
104 paddr
= (hwaddr
)(pte
>> PTE_PPN_SHIFT
) << PGSHIFT
;
107 /* PTE has to be valid */
109 if (attr
& (PTE_R
| PTE_W
| PTE_X
)) {
111 * A leaf PTE has been found
113 * If current PTE's permission bits differ from the last one,
114 * or current PTE's ppn does not make a contiguous physical
115 * address block together with the last one, print out the last
116 * contiguous mapped block details.
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
);
131 /* pointer to the next level of the page table */
132 walk_pte(mon
, paddr
, start
, level
- 1, ptidxbits
, ptesize
,
133 va_bits
, vbase
, pbase
, last_paddr
,
134 last_size
, last_attr
);
143 static void mem_info_svxx(Monitor
*mon
, CPUArchState
*env
)
145 int levels
, ptidxbits
, ptesize
, vm
, va_bits
;
150 target_ulong last_size
;
153 base
= (hwaddr
)get_field(env
->satp
, SATP_PPN
) << PGSHIFT
;
155 vm
= get_field(env
->satp
, SATP_MODE
);
178 g_assert_not_reached();
182 /* calculate virtual address bits */
183 va_bits
= PGSHIFT
+ levels
* ptidxbits
;
186 print_pte_header(mon
);
194 /* walk page tables, starting from address 0 */
195 walk_pte(mon
, base
, 0, levels
- 1, ptidxbits
, ptesize
, va_bits
,
196 &vbase
, &pbase
, &last_paddr
, &last_size
, &last_attr
);
198 /* don't forget the last one */
199 print_pte(mon
, va_bits
, vbase
, pbase
,
200 last_paddr
+ last_size
- pbase
, last_attr
);
203 void hmp_info_mem(Monitor
*mon
, const QDict
*qdict
)
207 env
= mon_get_cpu_env(mon
);
209 monitor_printf(mon
, "No CPU available\n");
213 if (!riscv_feature(env
, RISCV_FEATURE_MMU
)) {
214 monitor_printf(mon
, "S-mode MMU unavailable\n");
218 if (!(env
->satp
& SATP_MODE
)) {
219 monitor_printf(mon
, "No translation or protection\n");
223 mem_info_svxx(mon
, env
);