1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24: #include "hw/hw.h"
25: #include "hw/usb.h"
26: #include "hw/pcmcia.h"
27: #include "hw/pc.h"
28: #include "hw/pci.h"
29: #include "gdbstub.h"
30: #include "net.h"
31: #include "qemu-char.h"
32: #include "sysemu.h"
33: #include "console.h"
34: #include "block.h"
35: #include "audio/audio.h"
36: #include "disas.h"
37: #include <dirent.h>
38:
39: #ifdef CONFIG_PROFILER
40: #include "qemu-timer.h"
41: #endif
42:
43:
44:
45:
46: #ifndef offsetof
47: #define offsetof(type, field) ((size_t) &((type *)0)->field)
48: #endif
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64: typedef struct term_cmd_t {
65: const char *name;
66: const char *args_type;
67: void (*handler)();
68: const char *params;
69: const char *help;
70: } term_cmd_t;
71:
72: #define MAX_MON 4
73: static CharDriverState *monitor_hd[MAX_MON];
74: static int hide_banner;
75:
76: static term_cmd_t term_cmds[];
77: static term_cmd_t info_cmds[];
78:
79: static uint8_t term_outbuf[1024];
80: static int term_outbuf_index;
81:
82: static void monitor_start_input(void);
83:
84: CPUState *mon_cpu = NULL;
85:
86: void term_flush(void)
87: {
88: int i;
89: if (term_outbuf_index > 0) {
90: for (i = 0; i < MAX_MON; i++)
91: if (monitor_hd[i] && monitor_hd[i]->focus == 0)
92: qemu_chr_write(monitor_hd[i], term_outbuf, term_outbuf_index);
93: term_outbuf_index = 0;
94: }
95: }
96:
97:
98: void term_puts(const char *str)
99: {
100: char c;
101: for(;;) {
102: c = *str++;
103: if (c == '\0')
104: break;
105: if (c == '\n')
106: term_outbuf[term_outbuf_index++] = '\r';
107: term_outbuf[term_outbuf_index++] = c;
108: if (term_outbuf_index >= (sizeof(term_outbuf) - 1) ||
109: c == '\n')
110: term_flush();
111: }
112: }
113:
114: void term_vprintf(const char *fmt, va_list ap)
115: {
116: char buf[4096];
117: vsnprintf(buf, sizeof(buf), fmt, ap);
118: term_puts(buf);
119: }
120:
121: void term_printf(const char *fmt, ...)
122: {
123: va_list ap;
124: va_start(ap, fmt);
125: term_vprintf(fmt, ap);
126: va_end(ap);
127: }
128:
129: void term_print_filename(const char *filename)
130: {
131: int i;
132:
133: for (i = 0; filename[i]; i++) {
134: switch (filename[i]) {
135: case ' ':
136: case '"':
137: case '\\':
138: term_printf("\\%c", filename[i]);
139: break;
140: case '\t':
141: term_printf("\\t");
142: break;
143: case '\r':
144: term_printf("\\r");
145: break;
146: case '\n':
147: term_printf("\\n");
148: break;
149: default:
150: term_printf("%c", filename[i]);
151: break;
152: }
153: }
154: }
155:
156: static int monitor_fprintf(FILE *stream, const char *fmt, ...)
157: {
158: va_list ap;
159: va_start(ap, fmt);
160: term_vprintf(fmt, ap);
161: va_end(ap);
162: return 0;
163: }
164:
165: static int compare_cmd(const char *name, const char *list)
166: {
167: const char *p, *pstart;
168: int len;
169: len = strlen(name);
170: p = list;
171: for(;;) {
172: pstart = p;
173: p = strchr(p, '|');
174: if (!p)
175: p = pstart + strlen(pstart);
176: if ((p - pstart) == len && !memcmp(pstart, name, len))
177: return 1;
178: if (*p == '\0')
179: break;
180: p++;
181: }
182: return 0;
183: }
184:
185: static void help_cmd1(term_cmd_t *cmds, const char *prefix, const char *name)
186: {
187: term_cmd_t *cmd;
188:
189: for(cmd = cmds; cmd->name != NULL; cmd++) {
190: if (!name || !strcmp(name, cmd->name))
191: term_printf("%s%s %s -- %s\n", prefix, cmd->name, cmd->params, cmd->help);
192: }
193: }
194:
195: static void help_cmd(const char *name)
196: {
197: if (name && !strcmp(name, "info")) {
198: help_cmd1(info_cmds, "info ", NULL);
199: } else {
200: help_cmd1(term_cmds, "", name);
201: if (name && !strcmp(name, "log")) {
202: CPULogItem *item;
203: term_printf("Log items (comma separated):\n");
204: term_printf("%-10s %s\n", "none", "remove all logs");
205: for(item = cpu_log_items; item->mask != 0; item++) {
206: term_printf("%-10s %s\n", item->name, item->help);
207: }
208: }
209: }
210: }
211:
212: static void do_help(const char *name)
213: {
214: help_cmd(name);
215: }
216:
217: static void do_commit(const char *device)
218: {
219: int i, all_devices;
220:
221: all_devices = !strcmp(device, "all");
222: for (i = 0; i < nb_drives; i++) {
223: if (all_devices ||
224: !strcmp(bdrv_get_device_name(drives_table[i].bdrv), device))
225: bdrv_commit(drives_table[i].bdrv);
226: }
227: }
228:
229: static void do_info(const char *item)
230: {
231: term_cmd_t *cmd;
232:
233: if (!item)
234: goto help;
235: for(cmd = info_cmds; cmd->name != NULL; cmd++) {
236: if (compare_cmd(item, cmd->name))
237: goto found;
238: }
239: help:
240: help_cmd("info");
241: return;
242: found:
243: cmd->handler();
244: }
245:
246: static void do_info_version(void)
247: {
248: term_printf("%s\n", QEMU_VERSION);
249: }
250:
251: static void do_info_name(void)
252: {
253: if (qemu_name)
254: term_printf("%s\n", qemu_name);
255: }
256:
257: static void do_info_block(void)
258: {
259: bdrv_info();
260: }
261:
262: static void do_info_blockstats(void)
263: {
264: bdrv_info_stats();
265: }
266:
267:
268: static int mon_set_cpu(int cpu_index)
269: {
270: CPUState *env;
271:
272: for(env = first_cpu; env != NULL; env = env->next_cpu) {
273: if (env->cpu_index == cpu_index) {
274: mon_cpu = env;
275: return 0;
276: }
277: }
278: return -1;
279: }
280:
281: static CPUState *mon_get_cpu(void)
282: {
283: if (!mon_cpu) {
284: mon_set_cpu(0);
285: }
286: return mon_cpu;
287: }
288:
289: static void do_info_registers(void)
290: {
291: CPUState *env;
292: env = mon_get_cpu();
293: if (!env)
294: return;
295: #ifdef TARGET_I386
296: cpu_dump_state(env, NULL, monitor_fprintf,
297: X86_DUMP_FPU);
298: #else
299: cpu_dump_state(env, NULL, monitor_fprintf,
300: 0);
301: #endif
302: }
303:
304: static void do_info_cpus(void)
305: {
306: CPUState *env;
307:
308:
309: mon_get_cpu();
310:
311: for(env = first_cpu; env != NULL; env = env->next_cpu) {
312: term_printf("%c CPU #%d:",
313: (env == mon_cpu) ? '*' : ' ',
314: env->cpu_index);
315: #if defined(TARGET_I386)
316: term_printf(" pc=0x" TARGET_FMT_lx, env->eip + env->segs[R_CS].base);
317: if (env->hflags & HF_HALTED_MASK)
318: term_printf(" (halted)");
319: #elif defined(TARGET_PPC)
320: term_printf(" nip=0x" TARGET_FMT_lx, env->nip);
321: if (env->halted)
322: term_printf(" (halted)");
323: #elif defined(TARGET_SPARC)
324: term_printf(" pc=0x" TARGET_FMT_lx " npc=0x" TARGET_FMT_lx, env->pc, env->npc);
325: if (env->halted)
326: term_printf(" (halted)");
327: #elif defined(TARGET_MIPS)
328: term_printf(" PC=0x" TARGET_FMT_lx, env->PC[env->current_tc]);
329: if (env->halted)
330: term_printf(" (halted)");
331: #endif
332: term_printf("\n");
333: }
334: }
335:
336: static void do_cpu_set(int index)
337: {
338: if (mon_set_cpu(index) < 0)
339: term_printf("Invalid CPU index\n");
340: }
341:
342: static void do_info_jit(void)
343: {
344: dump_exec_info(NULL, monitor_fprintf);
345: }
346:
347: static void do_info_history (void)
348: {
349: int i;
350: const char *str;
351:
352: i = 0;
353: for(;;) {
354: str = readline_get_history(i);
355: if (!str)
356: break;
357: term_printf("%d: '%s'\n", i, str);
358: i++;
359: }
360: }
361:
362: #if defined(TARGET_PPC)
363:
364: static void do_info_cpu_stats (void)
365: {
366: CPUState *env;
367:
368: env = mon_get_cpu();
369: cpu_dump_statistics(env, NULL, &monitor_fprintf, 0);
370: }
371: #endif
372:
373: static void do_quit(void)
374: {
375: exit(0);
376: }
377:
378: static int eject_device(BlockDriverState *bs, int force)
379: {
380: if (bdrv_is_inserted(bs)) {
381: if (!force) {
382: if (!bdrv_is_removable(bs)) {
383: term_printf("device is not removable\n");
384: return -1;
385: }
386: if (bdrv_is_locked(bs)) {
387: term_printf("device is locked\n");
388: return -1;
389: }
390: }
391: bdrv_close(bs);
392: }
393: return 0;
394: }
395:
396: static void do_eject(int force, const char *filename)
397: {
398: BlockDriverState *bs;
399:
400: bs = bdrv_find(filename);
401: if (!bs) {
402: term_printf("device not found\n");
403: return;
404: }
405: eject_device(bs, force);
406: }
407:
408: static void do_change_block(const char *device, const char *filename)
409: {
410: BlockDriverState *bs;
411:
412: bs = bdrv_find(device);
413: if (!bs) {
414: term_printf("device not found\n");
415: return;
416: }
417: if (eject_device(bs, 0) < 0)
418: return;
419: bdrv_open(bs, filename, 0);
420: qemu_key_check(bs, filename);
421: }
422:
423: static void do_change_vnc(const char *target)
424: {
425: if (strcmp(target, "passwd") == 0 ||
426: strcmp(target, "password") == 0) {
427: char password[9];
428: monitor_readline("Password: ", 1, password, sizeof(password)-1);
429: password[sizeof(password)-1] = '\0';
430: if (vnc_display_password(NULL, password) < 0)
431: term_printf("could not set VNC server password\n");
432: } else {
433: if (vnc_display_open(NULL, target) < 0)
434: term_printf("could not start VNC server on %s\n", target);
435: }
436: }
437:
438: static void do_change(const char *device, const char *target)
439: {
440: if (strcmp(device, "vnc") == 0) {
441: do_change_vnc(target);
442: } else {
443: do_change_block(device, target);
444: }
445: }
446:
447: static void do_screen_dump(const char *filename)
448: {
449: vga_hw_screen_dump(filename);
450: }
451:
452: static void do_logfile(const char *filename)
453: {
454: cpu_set_log_filename(filename);
455: }
456:
457: static void do_log(const char *items)
458: {
459: int mask;
460:
461: if (!strcmp(items, "none")) {
462: mask = 0;
463: } else {
464: mask = cpu_str_to_log_mask(items);
465: if (!mask) {
466: help_cmd("log");
467: return;
468: }
469: }
470: cpu_set_log(mask);
471: }
472:
473: static void do_stop(void)
474: {
475: vm_stop(EXCP_INTERRUPT);
476: }
477:
478: static void do_cont(void)
479: {
480: vm_start();
481: }
482:
483: #ifdef CONFIG_GDBSTUB
484: static void do_gdbserver(const char *port)
485: {
486: if (!port)
487: port = DEFAULT_GDBSTUB_PORT;
488: if (gdbserver_start(port) < 0) {
489: qemu_printf("Could not open gdbserver socket on port '%s'\n", port);
490: } else {
491: qemu_printf("Waiting gdb connection on port '%s'\n", port);
492: }
493: }
494: #endif
495:
496: static void term_printc(int c)
497: {
498: term_printf("'");
499: switch(c) {
500: case '\'':
501: term_printf("\\'");
502: break;
503: case '\\':
504: term_printf("\\\\");
505: break;
506: case '\n':
507: term_printf("\\n");
508: break;
509: case '\r':
510: term_printf("\\r");
511: break;
512: default:
513: if (c >= 32 && c <= 126) {
514: term_printf("%c", c);
515: } else {
516: term_printf("\\x%02x", c);
517: }
518: break;
519: }
520: term_printf("'");
521: }
522:
523: static void memory_dump(int count, int format, int wsize,
524: target_phys_addr_t addr, int is_physical)
525: {
526: CPUState *env;
527: int nb_per_line, l, line_size, i, max_digits, len;
528: uint8_t buf[16];
529: uint64_t v;
530:
531: if (format == 'i') {
532: int flags;
533: flags = 0;
534: env = mon_get_cpu();
535: if (!env && !is_physical)
536: return;
537: #ifdef TARGET_I386
538: if (wsize == 2) {
539: flags = 1;
540: } else if (wsize == 4) {
541: flags = 0;
542: } else {
543:
544: flags = 0;
545: if (env) {
546: #ifdef TARGET_X86_64
547: if ((env->efer & MSR_EFER_LMA) &&
548: (env->segs[R_CS].flags & DESC_L_MASK))
549: flags = 2;
550: else
551: #endif
552: if (!(env->segs[R_CS].flags & DESC_B_MASK))
553: flags = 1;
554: }
555: }
556: #endif
557: monitor_disas(env, addr, count, is_physical, flags);
558: return;
559: }
560:
561: len = wsize * count;
562: if (wsize == 1)
563: line_size = 8;
564: else
565: line_size = 16;
566: nb_per_line = line_size / wsize;
567: max_digits = 0;
568:
569: switch(format) {
570: case 'o':
571: max_digits = (wsize * 8 + 2) / 3;
572: break;
573: default:
574: case 'x':
575: max_digits = (wsize * 8) / 4;
576: break;
577: case 'u':
578: case 'd':
579: max_digits = (wsize * 8 * 10 + 32) / 33;
580: break;
581: case 'c':
582: wsize = 1;
583: break;
584: }
585:
586: while (len > 0) {
587: if (is_physical)
588: term_printf(TARGET_FMT_plx ":", addr);
589: else
590: term_printf(TARGET_FMT_lx ":", (target_ulong)addr);
591: l = len;
592: if (l > line_size)
593: l = line_size;
594: if (is_physical) {
595: cpu_physical_memory_rw(addr, buf, l, 0);
596: } else {
597: env = mon_get_cpu();
598: if (!env)
599: break;
600: cpu_memory_rw_debug(env, addr, buf, l, 0);
601: }
602: i = 0;
603: while (i < l) {
604: switch(wsize) {
605: default:
606: case 1:
607: v = ldub_raw(buf + i);
608: break;
609: case 2:
610: v = lduw_raw(buf + i);
611: break;
612: case 4:
613: v = (uint32_t)ldl_raw(buf + i);
614: break;
615: case 8:
616: v = ldq_raw(buf + i);
617: break;
618: }
619: term_printf(" ");
620: switch(format) {
621: case 'o':
622: term_printf("%#*" PRIo64, max_digits, v);
623: break;
624: