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
@ -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 */
|
||||
|
Loading…
Reference in New Issue
Block a user