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: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk>
Reviewed-by: Laurent Vivier <laurent@vivier.eu>
Message-Id: <20220305150957.5053-9-mark.cave-ayland@ilande.co.uk>
Signed-off-by: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk>
This commit is contained in:
Mark Cave-Ayland 2022-03-05 15:09:53 +00:00
parent 6c72669872
commit 409e9f7131
4 changed files with 121 additions and 0 deletions

View File

@ -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

View File

@ -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,

View File

@ -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 */

View File

@ -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 */