ddb: Add 'show gic <name>' and 'show all gics' commands.

To handle the different register layouts for different versions, add a
GIC_DB_SHOW() method.  Currently this hook is only implemented for
versions 1 and 2.

Sponsored by:	University of Cambridge, Google, Inc.
Differential Revision:	https://reviews.freebsd.org/D34415
This commit is contained in:
John Baldwin 2022-03-10 15:39:37 -08:00
parent f5a2e7b0e8
commit 904a13759c
2 changed files with 113 additions and 0 deletions

View File

@ -37,6 +37,7 @@
__FBSDID("$FreeBSD$");
#include "opt_acpi.h"
#include "opt_ddb.h"
#include "opt_platform.h"
#include <sys/param.h>
@ -72,6 +73,11 @@ __FBSDID("$FreeBSD$");
#include <dev/acpica/acpivar.h>
#endif
#ifdef DDB
#include <ddb/ddb.h>
#include <ddb/db_lex.h>
#endif
#include <arm/arm/gic.h>
#include <arm/arm/gic_common.h>
@ -1147,6 +1153,58 @@ arm_gic_release_msix(device_t dev, struct intr_irqsrc *isrc)
return (0);
}
#ifdef DDB
static void
arm_gic_db_show(device_t dev)
{
struct arm_gic_softc *sc = device_get_softc(dev);
uint32_t val;
u_int i;
db_printf("%s CPU registers:\n", device_get_nameunit(dev));
db_printf(" CTLR: %08x PMR: %08x BPR: %08x RPR: %08x\n",
gic_c_read_4(sc, GICC_CTLR), gic_c_read_4(sc, GICC_PMR),
gic_c_read_4(sc, GICC_BPR), gic_c_read_4(sc, GICC_RPR));
db_printf("HPPIR: %08x IIDR: %08x\n", gic_c_read_4(sc, GICC_HPPIR),
gic_c_read_4(sc, GICC_IIDR));
db_printf("%s Distributor registers:\n", device_get_nameunit(dev));
db_printf(" CTLR: %08x TYPER: %08x IIDR: %08x\n",
gic_d_read_4(sc, GICD_CTLR), gic_d_read_4(sc, GICD_TYPER),
gic_d_read_4(sc, GICD_IIDR));
for (i = 0; i < sc->nirqs; i++) {
if (i <= GIC_LAST_SGI)
db_printf("SGI %2u ", i);
else if (i <= GIC_LAST_PPI)
db_printf("PPI %2u ", i - GIC_FIRST_PPI);
else
db_printf("SPI %2u ", i - GIC_FIRST_SPI);
db_printf(" grp:%u",
!!(gic_d_read_4(sc, GICD_IGROUPR(i)) & GICD_I_MASK(i)));
db_printf(" enable:%u pend:%u active:%u",
!!(gic_d_read_4(sc, GICD_ISENABLER(i)) & GICD_I_MASK(i)),
!!(gic_d_read_4(sc, GICD_ISPENDR(i)) & GICD_I_MASK(i)),
!!(gic_d_read_4(sc, GICD_ISACTIVER(i)) & GICD_I_MASK(i)));
db_printf(" pri:%u",
(gic_d_read_4(sc, GICD_IPRIORITYR(i)) >> 8 * (i & 0x3)) &
0xff);
db_printf(" trg:%u",
(gic_d_read_4(sc, GICD_ITARGETSR(i)) >> 8 * (i & 0x3)) &
0xff);
val = gic_d_read_4(sc, GICD_ICFGR(i)) >> 2 * (i & 0xf);
if ((val & GICD_ICFGR_POL_MASK) == GICD_ICFGR_POL_LOW)
db_printf(" LO");
else
db_printf(" HI");
if ((val & GICD_ICFGR_TRIG_MASK) == GICD_ICFGR_TRIG_LVL)
db_printf(" LV");
else
db_printf(" ED");
db_printf("\n");
}
}
#endif
static device_method_t arm_gic_methods[] = {
/* Bus interface */
DEVMETHOD(bus_print_child, arm_gic_print_child),
@ -1179,6 +1237,9 @@ static device_method_t arm_gic_methods[] = {
DEVMETHOD(gic_release_msi, arm_gic_release_msi),
DEVMETHOD(gic_alloc_msix, arm_gic_alloc_msix),
DEVMETHOD(gic_release_msix, arm_gic_release_msix),
#ifdef DDB
DEVMETHOD(gic_db_show, arm_gic_db_show),
#endif
{ 0, 0 }
};
@ -1186,6 +1247,54 @@ static device_method_t arm_gic_methods[] = {
DEFINE_CLASS_0(gic, arm_gic_driver, arm_gic_methods,
sizeof(struct arm_gic_softc));
#ifdef DDB
DB_FUNC(gic, db_show_gic, db_show_table, CS_OWN, NULL)
{
device_t dev;
int t;
bool valid;
valid = false;
t = db_read_token();
if (t == tIDENT) {
dev = device_lookup_by_name(db_tok_string);
valid = true;
}
db_skip_to_eol();
if (!valid) {
db_printf("usage: show gic <name>\n");
return;
}
if (dev == NULL) {
db_printf("device not found\n");
return;
}
GIC_DB_SHOW(dev);
}
DB_SHOW_ALL_COMMAND(gics, db_show_all_gics)
{
devclass_t dc;
device_t dev;
int i;
dc = devclass_find("gic");
if (dc == NULL)
return;
for (i = 0; i < devclass_get_maxunit(dc); i++) {
dev = devclass_get_device(dc, i);
if (dev != NULL)
GIC_DB_SHOW(dev);
if (db_pager_quit)
break;
}
}
#endif
/*
* GICv2m support -- the GICv2 MSI/MSI-X controller.
*/

View File

@ -67,3 +67,7 @@ METHOD int release_msix {
device_t dev;
struct intr_irqsrc *isrc;
};
METHOD void db_show {
device_t dev;
};