Skip to content
Snippets Groups Projects
Commit 409e9f71 authored by Mark Cave-Ayland's avatar Mark Cave-Ayland
Browse files

mos6522: add "info via" HMP command for debugging


This displays detailed information about the device registers and timers to aid
debugging problems with timers and interrupts.

Currently the QAPI generators for HumanReadableText don't work correctly if
used in qapi/target-misc.json when a non-specified target is built, so for
now manually add a hmp_info_via() wrapper until direct support for per-device
HMP/QMP commands is implemented.

Signed-off-by: default avatarMark Cave-Ayland <mark.cave-ayland@ilande.co.uk>
Reviewed-by: default avatarLaurent Vivier <laurent@vivier.eu>
Message-Id: <20220305150957.5053-9-mark.cave-ayland@ilande.co.uk>
Signed-off-by: default avatarMark Cave-Ayland <mark.cave-ayland@ilande.co.uk>
parent 6c726698
No related branches found
No related tags found
No related merge requests found
......@@ -879,3 +879,18 @@ SRST
``info sgx``
Show intel SGX information.
ERST
#if defined(TARGET_M68K) || defined(TARGET_PPC)
{
.name = "via",
.args_type = "",
.params = "",
.help = "show guest mos6522 VIA devices",
.cmd = hmp_info_via,
},
#endif
SRST
``info via``
Show guest mos6522 VIA devices.
ERST
......@@ -30,6 +30,9 @@
#include "hw/misc/mos6522.h"
#include "hw/qdev-properties.h"
#include "migration/vmstate.h"
#include "monitor/monitor.h"
#include "monitor/hmp.h"
#include "qapi/type-helpers.h"
#include "qemu/timer.h"
#include "qemu/cutils.h"
#include "qemu/log.h"
......@@ -415,6 +418,106 @@ void mos6522_write(void *opaque, hwaddr addr, uint64_t val, unsigned size)
}
}
static int qmp_x_query_via_foreach(Object *obj, void *opaque)
{
GString *buf = opaque;
if (object_dynamic_cast(obj, TYPE_MOS6522)) {
MOS6522State *s = MOS6522(obj);
int64_t now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
uint16_t t1counter = get_counter(s, &s->timers[0]);
uint16_t t2counter = get_counter(s, &s->timers[1]);
g_string_append_printf(buf, "%s:\n", object_get_typename(obj));
g_string_append_printf(buf, " Registers:\n");
g_string_append_printf(buf, " %-*s: 0x%x\n", 4,
mos6522_reg_names[0], s->b);
g_string_append_printf(buf, " %-*s: 0x%x\n", 4,
mos6522_reg_names[1], s->a);
g_string_append_printf(buf, " %-*s: 0x%x\n", 4,
mos6522_reg_names[2], s->dirb);
g_string_append_printf(buf, " %-*s: 0x%x\n", 4,
mos6522_reg_names[3], s->dira);
g_string_append_printf(buf, " %-*s: 0x%x\n", 4,
mos6522_reg_names[4], t1counter & 0xff);
g_string_append_printf(buf, " %-*s: 0x%x\n", 4,
mos6522_reg_names[5], t1counter >> 8);
g_string_append_printf(buf, " %-*s: 0x%x\n", 4,
mos6522_reg_names[6],
s->timers[0].latch & 0xff);
g_string_append_printf(buf, " %-*s: 0x%x\n", 4,
mos6522_reg_names[7],
s->timers[0].latch >> 8);
g_string_append_printf(buf, " %-*s: 0x%x\n", 4,
mos6522_reg_names[8], t2counter & 0xff);
g_string_append_printf(buf, " %-*s: 0x%x\n", 4,
mos6522_reg_names[9], t2counter >> 8);
g_string_append_printf(buf, " %-*s: 0x%x\n", 4,
mos6522_reg_names[10], s->sr);
g_string_append_printf(buf, " %-*s: 0x%x\n", 4,
mos6522_reg_names[11], s->acr);
g_string_append_printf(buf, " %-*s: 0x%x\n", 4,
mos6522_reg_names[12], s->pcr);
g_string_append_printf(buf, " %-*s: 0x%x\n", 4,
mos6522_reg_names[13], s->ifr);
g_string_append_printf(buf, " %-*s: 0x%x\n", 4,
mos6522_reg_names[14], s->ier);
g_string_append_printf(buf, " Timers:\n");
g_string_append_printf(buf, " Using current time now(ns)=%"PRId64
"\n", now);
g_string_append_printf(buf, " T1 freq(hz)=%"PRId64
" mode=%s"
" counter=0x%x"
" latch=0x%x\n"
" load_time(ns)=%"PRId64
" next_irq_time(ns)=%"PRId64 "\n",
s->timers[0].frequency,
((s->acr & T1MODE) == T1MODE_CONT) ? "continuous"
: "one-shot",
t1counter,
s->timers[0].latch,
s->timers[0].load_time,
get_next_irq_time(s, &s->timers[0], now));
g_string_append_printf(buf, " T2 freq(hz)=%"PRId64
" mode=%s"
" counter=0x%x"
" latch=0x%x\n"
" load_time(ns)=%"PRId64
" next_irq_time(ns)=%"PRId64 "\n",
s->timers[1].frequency,
"one-shot",
t2counter,
s->timers[1].latch,
s->timers[1].load_time,
get_next_irq_time(s, &s->timers[1], now));
}
return 0;
}
static HumanReadableText *qmp_x_query_via(Error **errp)
{
g_autoptr(GString) buf = g_string_new("");
object_child_foreach_recursive(object_get_root(),
qmp_x_query_via_foreach, buf);
return human_readable_text_from_str(buf);
}
void hmp_info_via(Monitor *mon, const QDict *qdict)
{
Error *err = NULL;
g_autoptr(HumanReadableText) info = qmp_x_query_via(&err);
if (hmp_handle_error(mon, err)) {
return;
}
monitor_printf(mon, "%s", info->human_readable_text);
}
static const MemoryRegionOps mos6522_ops = {
.read = mos6522_read,
.write = mos6522_write,
......
......@@ -157,4 +157,6 @@ extern const VMStateDescription vmstate_mos6522;
uint64_t mos6522_read(void *opaque, hwaddr addr, unsigned size);
void mos6522_write(void *opaque, hwaddr addr, uint64_t val, unsigned size);
void hmp_info_via(Monitor *mon, const QDict *qdict);
#endif /* MOS6522_H */
......@@ -50,5 +50,6 @@ void hmp_mce(Monitor *mon, const QDict *qdict);
void hmp_info_local_apic(Monitor *mon, const QDict *qdict);
void hmp_info_sev(Monitor *mon, const QDict *qdict);
void hmp_info_sgx(Monitor *mon, const QDict *qdict);
void hmp_info_via(Monitor *mon, const QDict *qdict);
#endif /* MONITOR_HMP_TARGET_H */
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment