mirror of
https://github.com/Motorhead1991/qemu.git
synced 2025-08-04 00:03:54 -06:00
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:
parent
6c72669872
commit
409e9f7131
4 changed files with 121 additions and 0 deletions
|
@ -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,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue