xref: /qemu/monitor/hmp-cmds-target.c (revision fc524567087c2537b5103cdfc1d41e4f442892b6)
1 /*
2  * Miscellaneous target-dependent HMP commands
3  *
4  * Copyright (c) 2003-2004 Fabrice Bellard
5  *
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:
12  *
13  * The above copyright notice and this permission notice shall be included in
14  * all copies or substantial portions of the Software.
15  *
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.
23  */
24 
25 #include "qemu/osdep.h"
26 #include "disas/disas.h"
27 #include "system/address-spaces.h"
28 #include "system/memory.h"
29 #include "monitor/hmp-target.h"
30 #include "monitor/monitor-internal.h"
31 #include "qapi/error.h"
32 #include "qobject/qdict.h"
33 #include "system/hw_accel.h"
34 #include "exec/target_page.h"
35 
36 /* Set the current CPU defined by the user. Callers must hold BQL. */
monitor_set_cpu(Monitor * mon,int cpu_index)37 int monitor_set_cpu(Monitor *mon, int cpu_index)
38 {
39     CPUState *cpu;
40 
41     cpu = qemu_get_cpu(cpu_index);
42     if (cpu == NULL) {
43         return -1;
44     }
45     g_free(mon->mon_cpu_path);
46     mon->mon_cpu_path = object_get_canonical_path(OBJECT(cpu));
47     return 0;
48 }
49 
50 /* Callers must hold BQL. */
mon_get_cpu_sync(Monitor * mon,bool synchronize)51 static CPUState *mon_get_cpu_sync(Monitor *mon, bool synchronize)
52 {
53     CPUState *cpu = NULL;
54 
55     if (mon->mon_cpu_path) {
56         cpu = (CPUState *) object_resolve_path_type(mon->mon_cpu_path,
57                                                     TYPE_CPU, NULL);
58         if (!cpu) {
59             g_free(mon->mon_cpu_path);
60             mon->mon_cpu_path = NULL;
61         }
62     }
63     if (!mon->mon_cpu_path) {
64         if (!first_cpu) {
65             return NULL;
66         }
67         monitor_set_cpu(mon, first_cpu->cpu_index);
68         cpu = first_cpu;
69     }
70     assert(cpu != NULL);
71     if (synchronize) {
72         cpu_synchronize_state(cpu);
73     }
74     return cpu;
75 }
76 
mon_get_cpu(Monitor * mon)77 CPUState *mon_get_cpu(Monitor *mon)
78 {
79     return mon_get_cpu_sync(mon, true);
80 }
81 
mon_get_cpu_env(Monitor * mon)82 CPUArchState *mon_get_cpu_env(Monitor *mon)
83 {
84     CPUState *cs = mon_get_cpu(mon);
85 
86     return cs ? cpu_env(cs) : NULL;
87 }
88 
monitor_get_cpu_index(Monitor * mon)89 int monitor_get_cpu_index(Monitor *mon)
90 {
91     CPUState *cs = mon_get_cpu_sync(mon, false);
92 
93     return cs ? cs->cpu_index : UNASSIGNED_CPU_INDEX;
94 }
95 
hmp_info_registers(Monitor * mon,const QDict * qdict)96 void hmp_info_registers(Monitor *mon, const QDict *qdict)
97 {
98     bool all_cpus = qdict_get_try_bool(qdict, "cpustate_all", false);
99     int vcpu = qdict_get_try_int(qdict, "vcpu", -1);
100     CPUState *cs;
101 
102     if (all_cpus) {
103         CPU_FOREACH(cs) {
104             monitor_printf(mon, "\nCPU#%d\n", cs->cpu_index);
105             cpu_dump_state(cs, NULL, CPU_DUMP_FPU);
106         }
107     } else {
108         cs = vcpu >= 0 ? qemu_get_cpu(vcpu) : mon_get_cpu(mon);
109 
110         if (!cs) {
111             if (vcpu >= 0) {
112                 monitor_printf(mon, "CPU#%d not available\n", vcpu);
113             } else {
114                 monitor_printf(mon, "No CPU available\n");
115             }
116             return;
117         }
118 
119         monitor_printf(mon, "\nCPU#%d\n", cs->cpu_index);
120         cpu_dump_state(cs, NULL, CPU_DUMP_FPU);
121     }
122 }
123 
memory_dump(Monitor * mon,int count,int format,int wsize,hwaddr addr,int is_physical)124 static void memory_dump(Monitor *mon, int count, int format, int wsize,
125                         hwaddr addr, int is_physical)
126 {
127     int l, line_size, i, max_digits, len;
128     uint8_t buf[16];
129     uint64_t v;
130     CPUState *cs = mon_get_cpu(mon);
131 
132     if (!cs && (format == 'i' || !is_physical)) {
133         monitor_printf(mon, "Can not dump without CPU\n");
134         return;
135     }
136 
137     if (format == 'i') {
138         monitor_disas(mon, cs, addr, count, is_physical);
139         return;
140     }
141 
142     len = wsize * count;
143     if (wsize == 1) {
144         line_size = 8;
145     } else {
146         line_size = 16;
147     }
148     max_digits = 0;
149 
150     switch(format) {
151     case 'o':
152         max_digits = DIV_ROUND_UP(wsize * 8, 3);
153         break;
154     default:
155     case 'x':
156         max_digits = (wsize * 8) / 4;
157         break;
158     case 'u':
159     case 'd':
160         max_digits = DIV_ROUND_UP(wsize * 8 * 10, 33);
161         break;
162     case 'c':
163         wsize = 1;
164         break;
165     }
166 
167     while (len > 0) {
168         if (is_physical) {
169             monitor_printf(mon, HWADDR_FMT_plx ":", addr);
170         } else {
171             monitor_printf(mon, TARGET_FMT_lx ":", (target_ulong)addr);
172         }
173         l = len;
174         if (l > line_size)
175             l = line_size;
176         if (is_physical) {
177             AddressSpace *as = cs ? cs->as : &address_space_memory;
178             MemTxResult r = address_space_read(as, addr,
179                                                MEMTXATTRS_UNSPECIFIED, buf, l);
180             if (r != MEMTX_OK) {
181                 monitor_printf(mon, " Cannot access memory\n");
182                 break;
183             }
184         } else {
185             if (cpu_memory_rw_debug(cs, addr, buf, l, 0) < 0) {
186                 monitor_printf(mon, " Cannot access memory\n");
187                 break;
188             }
189         }
190         i = 0;
191         while (i < l) {
192             switch(wsize) {
193             default:
194             case 1:
195                 v = ldub_p(buf + i);
196                 break;
197             case 2:
198                 v = lduw_p(buf + i);
199                 break;
200             case 4:
201                 v = (uint32_t)ldl_p(buf + i);
202                 break;
203             case 8:
204                 v = ldq_p(buf + i);
205                 break;
206             }
207             monitor_printf(mon, " ");
208             switch(format) {
209             case 'o':
210                 monitor_printf(mon, "%#*" PRIo64, max_digits, v);
211                 break;
212             case 'x':
213                 monitor_printf(mon, "0x%0*" PRIx64, max_digits, v);
214                 break;
215             case 'u':
216                 monitor_printf(mon, "%*" PRIu64, max_digits, v);
217                 break;
218             case 'd':
219                 monitor_printf(mon, "%*" PRId64, max_digits, v);
220                 break;
221             case 'c':
222                 monitor_printc(mon, v);
223                 break;
224             }
225             i += wsize;
226         }
227         monitor_printf(mon, "\n");
228         addr += l;
229         len -= l;
230     }
231 }
232 
hmp_memory_dump(Monitor * mon,const QDict * qdict)233 void hmp_memory_dump(Monitor *mon, const QDict *qdict)
234 {
235     int count = qdict_get_int(qdict, "count");
236     int format = qdict_get_int(qdict, "format");
237     int size = qdict_get_int(qdict, "size");
238     target_long addr = qdict_get_int(qdict, "addr");
239 
240     memory_dump(mon, count, format, size, addr, 0);
241 }
242 
hmp_physical_memory_dump(Monitor * mon,const QDict * qdict)243 void hmp_physical_memory_dump(Monitor *mon, const QDict *qdict)
244 {
245     int count = qdict_get_int(qdict, "count");
246     int format = qdict_get_int(qdict, "format");
247     int size = qdict_get_int(qdict, "size");
248     hwaddr addr = qdict_get_int(qdict, "addr");
249 
250     memory_dump(mon, count, format, size, addr, 1);
251 }
252 
gpa2hva(MemoryRegion ** p_mr,hwaddr addr,uint64_t size,Error ** errp)253 void *gpa2hva(MemoryRegion **p_mr, hwaddr addr, uint64_t size, Error **errp)
254 {
255     Int128 gpa_region_size;
256     MemoryRegionSection mrs = memory_region_find(get_system_memory(),
257                                                  addr, size);
258 
259     if (!mrs.mr) {
260         error_setg(errp, "No memory is mapped at address 0x%" HWADDR_PRIx, addr);
261         return NULL;
262     }
263 
264     if (!memory_region_is_ram(mrs.mr) && !memory_region_is_romd(mrs.mr)) {
265         error_setg(errp, "Memory at address 0x%" HWADDR_PRIx " is not RAM", addr);
266         memory_region_unref(mrs.mr);
267         return NULL;
268     }
269 
270     gpa_region_size = int128_make64(size);
271     if (int128_lt(mrs.size, gpa_region_size)) {
272         error_setg(errp, "Size of memory region at 0x%" HWADDR_PRIx
273                    " exceeded.", addr);
274         memory_region_unref(mrs.mr);
275         return NULL;
276     }
277 
278     *p_mr = mrs.mr;
279     return qemu_map_ram_ptr(mrs.mr->ram_block, mrs.offset_within_region);
280 }
281 
hmp_gpa2hva(Monitor * mon,const QDict * qdict)282 void hmp_gpa2hva(Monitor *mon, const QDict *qdict)
283 {
284     hwaddr addr = qdict_get_int(qdict, "addr");
285     Error *local_err = NULL;
286     MemoryRegion *mr = NULL;
287     void *ptr;
288 
289     ptr = gpa2hva(&mr, addr, 1, &local_err);
290     if (local_err) {
291         error_report_err(local_err);
292         return;
293     }
294 
295     monitor_printf(mon, "Host virtual address for 0x%" HWADDR_PRIx
296                    " (%s) is %p\n",
297                    addr, mr->name, ptr);
298 
299     memory_region_unref(mr);
300 }
301 
hmp_gva2gpa(Monitor * mon,const QDict * qdict)302 void hmp_gva2gpa(Monitor *mon, const QDict *qdict)
303 {
304     target_ulong addr = qdict_get_int(qdict, "addr");
305     CPUState *cs = mon_get_cpu(mon);
306     hwaddr gpa;
307 
308     if (!cs) {
309         monitor_printf(mon, "No cpu\n");
310         return;
311     }
312 
313     gpa  = cpu_get_phys_page_debug(cs, addr & TARGET_PAGE_MASK);
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));
319     }
320 }
321 
322 #ifdef CONFIG_LINUX
vtop(void * ptr,Error ** errp)323 static uint64_t vtop(void *ptr, Error **errp)
324 {
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;
331 
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;
336     }
337 
338     /* Force copy-on-write if necessary.  */
339     qatomic_add((uint8_t *)ptr, 0);
340 
341     if (pread(fd, &pinfo, sizeof(pinfo), offset) != sizeof(pinfo)) {
342         error_setg_errno(errp, errno, "Cannot read pagemap");
343         goto out;
344     }
345     if ((pinfo & (1ull << 63)) == 0) {
346         error_setg(errp, "Page not present");
347         goto out;
348     }
349     ret = ((pinfo & 0x007fffffffffffffull) * pagesize) | (addr & (pagesize - 1));
350 
351 out:
352     close(fd);
353     return ret;
354 }
355 
hmp_gpa2hpa(Monitor * mon,const QDict * qdict)356 void hmp_gpa2hpa(Monitor *mon, const QDict *qdict)
357 {
358     hwaddr addr = qdict_get_int(qdict, "addr");
359     Error *local_err = NULL;
360     MemoryRegion *mr = NULL;
361     void *ptr;
362     uint64_t physaddr;
363 
364     ptr = gpa2hva(&mr, addr, 1, &local_err);
365     if (local_err) {
366         error_report_err(local_err);
367         return;
368     }
369 
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);
377     }
378 
379     memory_region_unref(mr);
380 }
381 #endif
382