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