Skip to content

Commit

Permalink
monitor: Fix crashes when using HMP commands without CPU
Browse files Browse the repository at this point in the history
When running certain HMP commands ("info registers", "info cpustats",
"info tlb", "nmi", "memsave" or dumping virtual memory) with the "none"
machine, QEMU crashes with a segmentation fault. This happens because the
"none" machine does not have any CPUs by default, but these HMP commands
did not check for a valid CPU pointer yet. Add such checks now, so we get
an error message about the missing CPU instead.

Signed-off-by: Thomas Huth <thuth@redhat.com>
Message-Id: <1484309555-1935-1-git-send-email-thuth@redhat.com>
Reviewed-by: Markus Armbruster <armbru@redhat.com>
Acked-by: David Gibson <david@gibson.dropbear.id.au>
Signed-off-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
  • Loading branch information
huth authored and dagrh committed Feb 21, 2017
1 parent 5fc0048 commit 854e67f
Show file tree
Hide file tree
Showing 7 changed files with 73 additions and 10 deletions.
8 changes: 7 additions & 1 deletion hmp.c
Expand Up @@ -1014,8 +1014,14 @@ void hmp_memsave(Monitor *mon, const QDict *qdict)
const char *filename = qdict_get_str(qdict, "filename");
uint64_t addr = qdict_get_int(qdict, "val");
Error *err = NULL;
int cpu_index = monitor_get_cpu_index();

qmp_memsave(addr, size, filename, true, monitor_get_cpu_index(), &err);
if (cpu_index < 0) {
monitor_printf(mon, "No CPU available\n");
return;
}

qmp_memsave(addr, size, filename, true, cpu_index, &err);
hmp_handle_error(mon, &err);
}

Expand Down
42 changes: 34 additions & 8 deletions monitor.c
Expand Up @@ -1026,6 +1026,9 @@ int monitor_set_cpu(int cpu_index)
CPUState *mon_get_cpu(void)
{
if (!cur_mon->mon_cpu) {
if (!first_cpu) {
return NULL;
}
monitor_set_cpu(first_cpu->cpu_index);
}
cpu_synchronize_state(cur_mon->mon_cpu);
Expand All @@ -1034,17 +1037,27 @@ CPUState *mon_get_cpu(void)

CPUArchState *mon_get_cpu_env(void)
{
return mon_get_cpu()->env_ptr;
CPUState *cs = mon_get_cpu();

return cs ? cs->env_ptr : NULL;
}

int monitor_get_cpu_index(void)
{
return mon_get_cpu()->cpu_index;
CPUState *cs = mon_get_cpu();

return cs ? cs->cpu_index : UNASSIGNED_CPU_INDEX;
}

static void hmp_info_registers(Monitor *mon, const QDict *qdict)
{
cpu_dump_state(mon_get_cpu(), (FILE *)mon, monitor_fprintf, CPU_DUMP_FPU);
CPUState *cs = mon_get_cpu();

if (!cs) {
monitor_printf(mon, "No CPU available\n");
return;
}
cpu_dump_state(cs, (FILE *)mon, monitor_fprintf, CPU_DUMP_FPU);
}

static void hmp_info_jit(Monitor *mon, const QDict *qdict)
Expand Down Expand Up @@ -1077,7 +1090,13 @@ static void hmp_info_history(Monitor *mon, const QDict *qdict)

static void hmp_info_cpustats(Monitor *mon, const QDict *qdict)
{
cpu_dump_statistics(mon_get_cpu(), (FILE *)mon, &monitor_fprintf, 0);
CPUState *cs = mon_get_cpu();

if (!cs) {
monitor_printf(mon, "No CPU available\n");
return;
}
cpu_dump_statistics(cs, (FILE *)mon, &monitor_fprintf, 0);
}

static void hmp_info_trace_events(Monitor *mon, const QDict *qdict)
Expand Down Expand Up @@ -1236,6 +1255,12 @@ static void memory_dump(Monitor *mon, int count, int format, int wsize,
int l, line_size, i, max_digits, len;
uint8_t buf[16];
uint64_t v;
CPUState *cs = mon_get_cpu();

if (!cs && (format == 'i' || !is_physical)) {
monitor_printf(mon, "Can not dump without CPU\n");
return;
}

if (format == 'i') {
int flags = 0;
Expand Down Expand Up @@ -1265,7 +1290,7 @@ static void memory_dump(Monitor *mon, int count, int format, int wsize,
flags = msr_le << 16;
flags |= env->bfd_mach;
#endif
monitor_disas(mon, mon_get_cpu(), addr, count, is_physical, flags);
monitor_disas(mon, cs, addr, count, is_physical, flags);
return;
}

Expand Down Expand Up @@ -1304,7 +1329,7 @@ static void memory_dump(Monitor *mon, int count, int format, int wsize,
if (is_physical) {
cpu_physical_memory_read(addr, buf, l);
} else {
if (cpu_memory_rw_debug(mon_get_cpu(), addr, buf, l, 0) < 0) {
if (cpu_memory_rw_debug(cs, addr, buf, l, 0) < 0) {
monitor_printf(mon, " Cannot access memory\n");
break;
}
Expand Down Expand Up @@ -2189,11 +2214,12 @@ expr_error(Monitor *mon, const char *fmt, ...)
static int get_monitor_def(target_long *pval, const char *name)
{
const MonitorDef *md = target_monitor_defs();
CPUState *cs = mon_get_cpu();
void *ptr;
uint64_t tmp = 0;
int ret;

if (md == NULL) {
if (cs == NULL || md == NULL) {
return -1;
}

Expand All @@ -2220,7 +2246,7 @@ static int get_monitor_def(target_long *pval, const char *name)
}
}

ret = target_get_monitor_def(mon_get_cpu(), name, &tmp);
ret = target_get_monitor_def(cs, name, &tmp);
if (!ret) {
*pval = (target_long) tmp;
}
Expand Down
16 changes: 15 additions & 1 deletion target/i386/monitor.c
Expand Up @@ -210,6 +210,10 @@ void hmp_info_tlb(Monitor *mon, const QDict *qdict)
CPUArchState *env;

env = mon_get_cpu_env();
if (!env) {
monitor_printf(mon, "No CPU available\n");
return;
}

if (!(env->cr[0] & CR0_PG_MASK)) {
monitor_printf(mon, "PG disabled\n");
Expand Down Expand Up @@ -529,6 +533,10 @@ void hmp_info_mem(Monitor *mon, const QDict *qdict)
CPUArchState *env;

env = mon_get_cpu_env();
if (!env) {
monitor_printf(mon, "No CPU available\n");
return;
}

if (!(env->cr[0] & CR0_PG_MASK)) {
monitor_printf(mon, "PG disabled\n");
Expand Down Expand Up @@ -624,7 +632,13 @@ const MonitorDef *target_monitor_defs(void)

void hmp_info_local_apic(Monitor *mon, const QDict *qdict)
{
x86_cpu_dump_local_apic_state(mon_get_cpu(), (FILE *)mon, monitor_fprintf,
CPUState *cs = mon_get_cpu();

if (!cs) {
monitor_printf(mon, "No CPU available\n");
return;
}
x86_cpu_dump_local_apic_state(cs, (FILE *)mon, monitor_fprintf,
CPU_DUMP_FPU);
}

Expand Down
4 changes: 4 additions & 0 deletions target/ppc/monitor.c
Expand Up @@ -62,6 +62,10 @@ void hmp_info_tlb(Monitor *mon, const QDict *qdict)
{
CPUArchState *env1 = mon_get_cpu_env();

if (!env1) {
monitor_printf(mon, "No CPU available\n");
return;
}
dump_mmu((FILE*)mon, (fprintf_function)monitor_printf, env1);
}

Expand Down
5 changes: 5 additions & 0 deletions target/sh4/monitor.c
Expand Up @@ -44,6 +44,11 @@ void hmp_info_tlb(Monitor *mon, const QDict *qdict)
CPUArchState *env = mon_get_cpu_env();
int i;

if (!env) {
monitor_printf(mon, "No CPU available\n");
return;
}

monitor_printf (mon, "ITLB:\n");
for (i = 0 ; i < ITLB_SIZE ; i++)
print_tlb (mon, i, &env->itlb[i]);
Expand Down
4 changes: 4 additions & 0 deletions target/sparc/monitor.c
Expand Up @@ -32,6 +32,10 @@ void hmp_info_tlb(Monitor *mon, const QDict *qdict)
{
CPUArchState *env1 = mon_get_cpu_env();

if (!env1) {
monitor_printf(mon, "No CPU available\n");
return;
}
dump_mmu((FILE*)mon, (fprintf_function)monitor_printf, env1);
}

Expand Down
4 changes: 4 additions & 0 deletions target/xtensa/monitor.c
Expand Up @@ -31,5 +31,9 @@ void hmp_info_tlb(Monitor *mon, const QDict *qdict)
{
CPUArchState *env1 = mon_get_cpu_env();

if (!env1) {
monitor_printf(mon, "No CPU available\n");
return;
}
dump_mmu((FILE*)mon, (fprintf_function)monitor_printf, env1);
}

0 comments on commit 854e67f

Please sign in to comment.