Merge tag 'pull-loongarch-20241016' of https://gitlab.com/gaosong/qemu into staging
[qemu/armbru.git] / monitor / hmp-cmds-target.c
blobff01cf9d8dbd833511c0c1bb6c92d1f7cbf9e37a
1 /*
2 * Miscellaneous target-dependent HMP commands
4 * Copyright (c) 2003-2004 Fabrice Bellard
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 * THE SOFTWARE.
25 #include "qemu/osdep.h"
26 #include "disas/disas.h"
27 #include "exec/address-spaces.h"
28 #include "exec/memory.h"
29 #include "monitor/hmp-target.h"
30 #include "monitor/monitor-internal.h"
31 #include "qapi/error.h"
32 #include "qapi/qmp/qdict.h"
33 #include "sysemu/hw_accel.h"
35 /* Set the current CPU defined by the user. Callers must hold BQL. */
36 int monitor_set_cpu(Monitor *mon, int cpu_index)
38 CPUState *cpu;
40 cpu = qemu_get_cpu(cpu_index);
41 if (cpu == NULL) {
42 return -1;
44 g_free(mon->mon_cpu_path);
45 mon->mon_cpu_path = object_get_canonical_path(OBJECT(cpu));
46 return 0;
49 /* Callers must hold BQL. */
50 static CPUState *mon_get_cpu_sync(Monitor *mon, bool synchronize)
52 CPUState *cpu = NULL;
54 if (mon->mon_cpu_path) {
55 cpu = (CPUState *) object_resolve_path_type(mon->mon_cpu_path,
56 TYPE_CPU, NULL);
57 if (!cpu) {
58 g_free(mon->mon_cpu_path);
59 mon->mon_cpu_path = NULL;
62 if (!mon->mon_cpu_path) {
63 if (!first_cpu) {
64 return NULL;
66 monitor_set_cpu(mon, first_cpu->cpu_index);
67 cpu = first_cpu;
69 assert(cpu != NULL);
70 if (synchronize) {
71 cpu_synchronize_state(cpu);
73 return cpu;
76 CPUState *mon_get_cpu(Monitor *mon)
78 return mon_get_cpu_sync(mon, true);
81 CPUArchState *mon_get_cpu_env(Monitor *mon)
83 CPUState *cs = mon_get_cpu(mon);
85 return cs ? cpu_env(cs) : NULL;
88 int monitor_get_cpu_index(Monitor *mon)
90 CPUState *cs = mon_get_cpu_sync(mon, false);
92 return cs ? cs->cpu_index : UNASSIGNED_CPU_INDEX;
95 void hmp_info_registers(Monitor *mon, const QDict *qdict)
97 bool all_cpus = qdict_get_try_bool(qdict, "cpustate_all", false);
98 int vcpu = qdict_get_try_int(qdict, "vcpu", -1);
99 CPUState *cs;
101 if (all_cpus) {
102 CPU_FOREACH(cs) {
103 monitor_printf(mon, "\nCPU#%d\n", cs->cpu_index);
104 cpu_dump_state(cs, NULL, CPU_DUMP_FPU);
106 } else {
107 cs = vcpu >= 0 ? qemu_get_cpu(vcpu) : mon_get_cpu(mon);
109 if (!cs) {
110 if (vcpu >= 0) {
111 monitor_printf(mon, "CPU#%d not available\n", vcpu);
112 } else {
113 monitor_printf(mon, "No CPU available\n");
115 return;
118 monitor_printf(mon, "\nCPU#%d\n", cs->cpu_index);
119 cpu_dump_state(cs, NULL, CPU_DUMP_FPU);
123 static void memory_dump(Monitor *mon, int count, int format, int wsize,
124 hwaddr addr, int is_physical)
126 int l, line_size, i, max_digits, len;
127 uint8_t buf[16];
128 uint64_t v;
129 CPUState *cs = mon_get_cpu(mon);
131 if (!cs && (format == 'i' || !is_physical)) {
132 monitor_printf(mon, "Can not dump without CPU\n");
133 return;
136 if (format == 'i') {
137 monitor_disas(mon, cs, addr, count, is_physical);
138 return;
141 len = wsize * count;
142 if (wsize == 1) {
143 line_size = 8;
144 } else {
145 line_size = 16;
147 max_digits = 0;
149 switch(format) {
150 case 'o':
151 max_digits = DIV_ROUND_UP(wsize * 8, 3);
152 break;
153 default:
154 case 'x':
155 max_digits = (wsize * 8) / 4;
156 break;
157 case 'u':
158 case 'd':
159 max_digits = DIV_ROUND_UP(wsize * 8 * 10, 33);
160 break;
161 case 'c':
162 wsize = 1;
163 break;
166 while (len > 0) {
167 if (is_physical) {
168 monitor_printf(mon, HWADDR_FMT_plx ":", addr);
169 } else {
170 monitor_printf(mon, TARGET_FMT_lx ":", (target_ulong)addr);
172 l = len;
173 if (l > line_size)
174 l = line_size;
175 if (is_physical) {
176 AddressSpace *as = cs ? cs->as : &address_space_memory;
177 MemTxResult r = address_space_read(as, addr,
178 MEMTXATTRS_UNSPECIFIED, buf, l);
179 if (r != MEMTX_OK) {
180 monitor_printf(mon, " Cannot access memory\n");
181 break;
183 } else {
184 if (cpu_memory_rw_debug(cs, addr, buf, l, 0) < 0) {
185 monitor_printf(mon, " Cannot access memory\n");
186 break;
189 i = 0;
190 while (i < l) {
191 switch(wsize) {
192 default:
193 case 1:
194 v = ldub_p(buf + i);
195 break;
196 case 2:
197 v = lduw_p(buf + i);
198 break;
199 case 4:
200 v = (uint32_t)ldl_p(buf + i);
201 break;
202 case 8:
203 v = ldq_p(buf + i);
204 break;
206 monitor_printf(mon, " ");
207 switch(format) {
208 case 'o':
209 monitor_printf(mon, "%#*" PRIo64, max_digits, v);
210 break;
211 case 'x':
212 monitor_printf(mon, "0x%0*" PRIx64, max_digits, v);
213 break;
214 case 'u':
215 monitor_printf(mon, "%*" PRIu64, max_digits, v);
216 break;
217 case 'd':
218 monitor_printf(mon, "%*" PRId64, max_digits, v);
219 break;
220 case 'c':
221 monitor_printc(mon, v);
222 break;
224 i += wsize;
226 monitor_printf(mon, "\n");
227 addr += l;
228 len -= l;
232 void hmp_memory_dump(Monitor *mon, const QDict *qdict)
234 int count = qdict_get_int(qdict, "count");
235 int format = qdict_get_int(qdict, "format");
236 int size = qdict_get_int(qdict, "size");
237 target_long addr = qdict_get_int(qdict, "addr");
239 memory_dump(mon, count, format, size, addr, 0);
242 void hmp_physical_memory_dump(Monitor *mon, const QDict *qdict)
244 int count = qdict_get_int(qdict, "count");
245 int format = qdict_get_int(qdict, "format");
246 int size = qdict_get_int(qdict, "size");
247 hwaddr addr = qdict_get_int(qdict, "addr");
249 memory_dump(mon, count, format, size, addr, 1);
252 void *gpa2hva(MemoryRegion **p_mr, hwaddr addr, uint64_t size, Error **errp)
254 Int128 gpa_region_size;
255 MemoryRegionSection mrs = memory_region_find(get_system_memory(),
256 addr, size);
258 if (!mrs.mr) {
259 error_setg(errp, "No memory is mapped at address 0x%" HWADDR_PRIx, addr);
260 return NULL;
263 if (!memory_region_is_ram(mrs.mr) && !memory_region_is_romd(mrs.mr)) {
264 error_setg(errp, "Memory at address 0x%" HWADDR_PRIx " is not RAM", addr);
265 memory_region_unref(mrs.mr);
266 return NULL;
269 gpa_region_size = int128_make64(size);
270 if (int128_lt(mrs.size, gpa_region_size)) {
271 error_setg(errp, "Size of memory region at 0x%" HWADDR_PRIx
272 " exceeded.", addr);
273 memory_region_unref(mrs.mr);
274 return NULL;
277 *p_mr = mrs.mr;
278 return qemu_map_ram_ptr(mrs.mr->ram_block, mrs.offset_within_region);
281 void hmp_gpa2hva(Monitor *mon, const QDict *qdict)
283 hwaddr addr = qdict_get_int(qdict, "addr");
284 Error *local_err = NULL;
285 MemoryRegion *mr = NULL;
286 void *ptr;
288 ptr = gpa2hva(&mr, addr, 1, &local_err);
289 if (local_err) {
290 error_report_err(local_err);
291 return;
294 monitor_printf(mon, "Host virtual address for 0x%" HWADDR_PRIx
295 " (%s) is %p\n",
296 addr, mr->name, ptr);
298 memory_region_unref(mr);
301 void hmp_gva2gpa(Monitor *mon, const QDict *qdict)
303 target_ulong addr = qdict_get_int(qdict, "addr");
304 MemTxAttrs attrs;
305 CPUState *cs = mon_get_cpu(mon);
306 hwaddr gpa;
308 if (!cs) {
309 monitor_printf(mon, "No cpu\n");
310 return;
313 gpa = cpu_get_phys_page_attrs_debug(cs, addr & TARGET_PAGE_MASK, &attrs);
314 if (gpa == -1) {
315 monitor_printf(mon, "Unmapped\n");
316 } else {
317 monitor_printf(mon, "gpa: %#" HWADDR_PRIx "\n",
318 gpa + (addr & ~TARGET_PAGE_MASK));
322 #ifdef CONFIG_LINUX
323 static uint64_t vtop(void *ptr, Error **errp)
325 uint64_t pinfo;
326 uint64_t ret = -1;
327 uintptr_t addr = (uintptr_t) ptr;
328 uintptr_t pagesize = qemu_real_host_page_size();
329 off_t offset = addr / pagesize * sizeof(pinfo);
330 int fd;
332 fd = open("/proc/self/pagemap", O_RDONLY);
333 if (fd == -1) {
334 error_setg_errno(errp, errno, "Cannot open /proc/self/pagemap");
335 return -1;
338 /* Force copy-on-write if necessary. */
339 qatomic_add((uint8_t *)ptr, 0);
341 if (pread(fd, &pinfo, sizeof(pinfo), offset) != sizeof(pinfo)) {
342 error_setg_errno(errp, errno, "Cannot read pagemap");
343 goto out;
345 if ((pinfo & (1ull << 63)) == 0) {
346 error_setg(errp, "Page not present");
347 goto out;
349 ret = ((pinfo & 0x007fffffffffffffull) * pagesize) | (addr & (pagesize - 1));
351 out:
352 close(fd);
353 return ret;
356 void hmp_gpa2hpa(Monitor *mon, const QDict *qdict)
358 hwaddr addr = qdict_get_int(qdict, "addr");
359 Error *local_err = NULL;
360 MemoryRegion *mr = NULL;
361 void *ptr;
362 uint64_t physaddr;
364 ptr = gpa2hva(&mr, addr, 1, &local_err);
365 if (local_err) {
366 error_report_err(local_err);
367 return;
370 physaddr = vtop(ptr, &local_err);
371 if (local_err) {
372 error_report_err(local_err);
373 } else {
374 monitor_printf(mon, "Host physical address for 0x%" HWADDR_PRIx
375 " (%s) is 0x%" PRIx64 "\n",
376 addr, mr->name, (uint64_t) physaddr);
379 memory_region_unref(mr);
381 #endif