Export tracing facility of GIC500 ITS block.

Possibility of tracing of processing message based interrupts is very
useful for debugging of PCIe driver, mainly for its MSI part.

MFC after: 1 week
This commit is contained in:
Michal Meloun 2020-04-29 14:31:25 +00:00
parent b33e1edd26
commit 015f223e0b
2 changed files with 105 additions and 0 deletions

View File

@ -220,6 +220,8 @@
(rev) << GITS_IIDR_REVISION_SHIFT | \
(impl) << GITS_IIDR_IMPLEMENTOR_SHIFT)
#define GITS_IIDR_IMPL_ARM (0x43B)
#define GITS_IIDR_PROD_GIC500 (0x0)
#define GITS_IIDR_IMPL_CAVIUM (0x34c)
#define GITS_IIDR_PROD_THUNDER (0xa1)
#define GITS_IIDR_VAR_THUNDER_1 (0x0)
@ -360,6 +362,18 @@
#define LPI_CONF_GROUP1 (1 << 1)
#define LPI_CONF_ENABLE (1 << 0)
/*
* GIC 500 ITS tracking facility
*/
#define GITS_TRKCTLR 0xC000
#define GITS_TRKR 0xC004
#define GITS_TRKDIDR 0xC008
#define GITS_TRKPIDR 0xC00C
#define GITS_TRKVIDR 0xC010
#define GITS_TRKTGTR 0xC014
#define GITS_TRKICR 0xC018
#define GITS_TRKLCR 0xC018
/*
* CPU interface
*/

View File

@ -49,7 +49,9 @@ __FBSDID("$FreeBSD$");
#include <sys/proc.h>
#include <sys/queue.h>
#include <sys/rman.h>
#include <sys/sbuf.h>
#include <sys/smp.h>
#include <sys/sysctl.h>
#include <sys/vmem.h>
#include <vm/vm.h>
@ -229,6 +231,7 @@ struct gicv3_its_irqsrc {
};
struct gicv3_its_softc {
device_t dev;
struct intr_pic *sc_pic;
struct resource *sc_its_res;
@ -262,6 +265,7 @@ struct gicv3_its_softc {
#define ITS_FLAGS_LPI_CONF_FLUSH 0x00000002
#define ITS_FLAGS_ERRATA_CAVIUM_22375 0x00000004
u_int sc_its_flags;
bool trace_enable;
};
static void *conf_base;
@ -712,6 +716,86 @@ its_init_cpu(device_t dev, struct gicv3_its_softc *sc)
return (0);
}
static int
gicv3_its_sysctl_trace_enable(SYSCTL_HANDLER_ARGS)
{
struct gicv3_its_softc *sc;
int rv;
sc = arg1;
rv = sysctl_handle_bool(oidp, &sc->trace_enable, 0, req);
if (rv != 0 || req->newptr == NULL)
return (rv);
if (sc->trace_enable)
gic_its_write_8(sc, GITS_TRKCTLR, 3);
else
gic_its_write_8(sc, GITS_TRKCTLR, 0);
return (0);
}
static int
gicv3_its_sysctl_trace_regs(SYSCTL_HANDLER_ARGS)
{
struct gicv3_its_softc *sc;
struct sbuf *sb;
int err;
sc = arg1;
sb = sbuf_new_for_sysctl(NULL, NULL, 128, req);
if (sb == NULL) {
device_printf(sc->dev, "Could not allocate sbuf for output.\n");
return (ENOMEM);
}
sbuf_cat(sb, "\n");
sbuf_printf(sb, "GITS_TRKCTLR: 0x%08X\n",
gic_its_read_4(sc, GITS_TRKCTLR));
sbuf_printf(sb, "GITS_TRKR: 0x%08X\n",
gic_its_read_4(sc, GITS_TRKR));
sbuf_printf(sb, "GITS_TRKDIDR: 0x%08X\n",
gic_its_read_4(sc, GITS_TRKDIDR));
sbuf_printf(sb, "GITS_TRKPIDR: 0x%08X\n",
gic_its_read_4(sc, GITS_TRKPIDR));
sbuf_printf(sb, "GITS_TRKVIDR: 0x%08X\n",
gic_its_read_4(sc, GITS_TRKVIDR));
sbuf_printf(sb, "GITS_TRKTGTR: 0x%08X\n",
gic_its_read_4(sc, GITS_TRKTGTR));
err = sbuf_finish(sb);
if (err)
device_printf(sc->dev, "Error finishing sbuf: %d\n", err);
sbuf_delete(sb);
return(err);
}
static int
gicv3_its_init_sysctl(struct gicv3_its_softc *sc)
{
struct sysctl_oid *oid, *child;
struct sysctl_ctx_list *ctx_list;
ctx_list = device_get_sysctl_ctx(sc->dev);
child = device_get_sysctl_tree(sc->dev);
oid = SYSCTL_ADD_NODE(ctx_list,
SYSCTL_CHILDREN(child), OID_AUTO, "tracing",
CTLFLAG_RD| CTLFLAG_MPSAFE, NULL, "Messages tracing");
if (oid == NULL)
return (ENXIO);
/* Add registers */
SYSCTL_ADD_PROC(ctx_list,
SYSCTL_CHILDREN(oid), OID_AUTO, "enable",
CTLTYPE_U8 | CTLFLAG_RW | CTLFLAG_MPSAFE, sc, 0,
gicv3_its_sysctl_trace_enable, "CU", "Enable tracing");
SYSCTL_ADD_PROC(ctx_list,
SYSCTL_CHILDREN(oid), OID_AUTO, "capture",
CTLTYPE_STRING | CTLFLAG_RW | CTLFLAG_MPSAFE, sc, 0,
gicv3_its_sysctl_trace_regs, "", "Captured tracing registers.");
return (0);
}
static int
gicv3_its_attach(device_t dev)
{
@ -811,6 +895,11 @@ gicv3_its_attach(device_t dev)
"%s,%u", name, i);
}
/* For GIC-500 install tracking sysctls. */
if ((iidr & (GITS_IIDR_PRODUCT_MASK | GITS_IIDR_IMPLEMENTOR_MASK)) ==
GITS_IIDR_RAW(GITS_IIDR_IMPL_ARM, GITS_IIDR_PROD_GIC500, 0, 0))
gicv3_its_init_sysctl(sc);
return (0);
}
@ -1717,6 +1806,7 @@ gicv3_its_fdt_attach(device_t dev)
int err;
sc = device_get_softc(dev);
sc->dev = dev;
err = gicv3_its_attach(dev);
if (err != 0)
return (err);
@ -1778,6 +1868,7 @@ gicv3_its_acpi_attach(device_t dev)
int err;
sc = device_get_softc(dev);
sc->dev = dev;
err = gicv3_its_attach(dev);
if (err != 0)
return (err);