svn commit: r360466 - head/sys/arm64/arm64

Michal Meloun mmel at FreeBSD.org
Wed Apr 29 14:31:26 UTC 2020


Author: mmel
Date: Wed Apr 29 14:31:25 2020
New Revision: 360466
URL: https://svnweb.freebsd.org/changeset/base/360466

Log:
  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

Modified:
  head/sys/arm64/arm64/gic_v3_reg.h
  head/sys/arm64/arm64/gicv3_its.c

Modified: head/sys/arm64/arm64/gic_v3_reg.h
==============================================================================
--- head/sys/arm64/arm64/gic_v3_reg.h	Wed Apr 29 14:15:21 2020	(r360465)
+++ head/sys/arm64/arm64/gic_v3_reg.h	Wed Apr 29 14:31:25 2020	(r360466)
@@ -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)
@@ -359,6 +361,18 @@
 #define		LPI_CONF_PRIO_MASK	(0xFC)
 #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

Modified: head/sys/arm64/arm64/gicv3_its.c
==============================================================================
--- head/sys/arm64/arm64/gicv3_its.c	Wed Apr 29 14:15:21 2020	(r360465)
+++ head/sys/arm64/arm64/gicv3_its.c	Wed Apr 29 14:31:25 2020	(r360466)
@@ -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;
@@ -713,6 +717,86 @@ its_init_cpu(device_t dev, struct gicv3_its_softc *sc)
 }
 
 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)
 {
 	struct gicv3_its_softc *sc;
@@ -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);


More information about the svn-src-all mailing list