From nobody Tue Nov 2 19:49:52 2021
X-Original-To: dev-commits-src-main@mlmmj.nyi.freebsd.org
Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1])
by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id 08C86183096B;
Tue, 2 Nov 2021 19:49:53 +0000 (UTC)
(envelope-from git@FreeBSD.org)
Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3])
(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)
key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256
client-signature RSA-PSS (4096 bits) client-digest SHA256)
(Client CN "mxrelay.nyi.freebsd.org", Issuer "R3" (verified OK))
by mx1.freebsd.org (Postfix) with ESMTPS id 4HkL8c60zLz4htl;
Tue, 2 Nov 2021 19:49:52 +0000 (UTC)
(envelope-from git@FreeBSD.org)
Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5])
(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)
key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256)
(Client did not present a certificate)
by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id AD0892E57;
Tue, 2 Nov 2021 19:49:52 +0000 (UTC)
(envelope-from git@FreeBSD.org)
Received: from gitrepo.freebsd.org ([127.0.1.44])
by gitrepo.freebsd.org (8.16.1/8.16.1) with ESMTP id 1A2Jnq9L059250;
Tue, 2 Nov 2021 19:49:52 GMT
(envelope-from git@gitrepo.freebsd.org)
Received: (from git@localhost)
by gitrepo.freebsd.org (8.16.1/8.16.1/Submit) id 1A2JnqBS059249;
Tue, 2 Nov 2021 19:49:52 GMT
(envelope-from git)
Date: Tue, 2 Nov 2021 19:49:52 GMT
Message-Id: <202111021949.1A2JnqBS059249@gitrepo.freebsd.org>
To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org,
dev-commits-src-main@FreeBSD.org
From: Ruslan Bukin
Subject: git: 4bb6991531b5 - main - arm/pmu: add ACPI attachment.
List-Id: Commit messages for the main branch of the src repository
List-Archive: https://lists.freebsd.org/archives/dev-commits-src-main
List-Help:
List-Post:
List-Subscribe:
List-Unsubscribe:
Sender: owner-dev-commits-src-main@freebsd.org
X-BeenThere: dev-commits-src-main@freebsd.org
MIME-Version: 1.0
Content-Type: text/plain; charset=utf-8
Content-Transfer-Encoding: 8bit
X-Git-Committer: br
X-Git-Repository: src
X-Git-Refname: refs/heads/main
X-Git-Reftype: branch
X-Git-Commit: 4bb6991531b528c89fdadd3316d80b885a7f9bdb
Auto-Submitted: auto-generated
X-ThisMailContainsUnwantedMimeParts: N
The branch main has been updated by br:
URL: https://cgit.FreeBSD.org/src/commit/?id=4bb6991531b528c89fdadd3316d80b885a7f9bdb
commit 4bb6991531b528c89fdadd3316d80b885a7f9bdb
Author: Ruslan Bukin
AuthorDate: 2021-11-02 19:35:29 +0000
Commit: Ruslan Bukin
CommitDate: 2021-11-02 19:35:29 +0000
arm/pmu: add ACPI attachment.
This makes hwpmc(4) sampling work on ACPI-based AArch64 systems.
Tested on ARM Neoverse N1.
Submitted by: Greg V
Reviewed by: jrtc27, mhorne
Differential Revision: https://reviews.freebsd.org/D24423
---
sys/arm/arm/pmu.h | 2 +-
sys/arm/arm/pmu_acpi.c | 195 +++++++++++++++++++++++++++++++++++++++++++++++++
sys/conf/files.arm64 | 1 +
3 files changed, 197 insertions(+), 1 deletion(-)
diff --git a/sys/arm/arm/pmu.h b/sys/arm/arm/pmu.h
index bfad6d9da282..657faba28e74 100644
--- a/sys/arm/arm/pmu.h
+++ b/sys/arm/arm/pmu.h
@@ -33,7 +33,7 @@
#ifndef _ARM_PMU_H_
#define _ARM_PMU_H_
-#define MAX_RLEN 8
+#define MAX_RLEN MAXCPU
struct pmu_intr {
struct resource *res;
diff --git a/sys/arm/arm/pmu_acpi.c b/sys/arm/arm/pmu_acpi.c
new file mode 100644
index 000000000000..b1378c24e833
--- /dev/null
+++ b/sys/arm/arm/pmu_acpi.c
@@ -0,0 +1,195 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ *
+ * Copyright (c) 2020 Greg V
+ * Copyright (c) 2021 Ruslan Bukin
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+
+#include "acpi_bus_if.h"
+#include "pmu.h"
+
+struct madt_ctx {
+ struct pmu_softc *sc;
+ int error;
+ int i;
+};
+
+static void
+madt_handler(ACPI_SUBTABLE_HEADER *entry, void *arg)
+{
+ ACPI_MADT_GENERIC_INTERRUPT *intr;
+ struct intr_map_data_acpi *ad;
+ struct intr_map_data *data;
+ struct madt_ctx *ctx;
+ struct pmu_softc *sc;
+ struct pcpu *pcpu;
+ int rid;
+ int cpuid;
+ int i;
+
+ ctx = arg;
+ sc = ctx->sc;
+ rid = ctx->i;
+ cpuid = -1;
+
+ if (ctx->error)
+ return;
+
+ if (entry->Type != ACPI_MADT_TYPE_GENERIC_INTERRUPT)
+ return;
+ intr = (ACPI_MADT_GENERIC_INTERRUPT *)entry;
+
+ for (i = 0; i < MAXCPU; i++) {
+ pcpu = pcpu_find(i);
+ if (pcpu != NULL && pcpu->pc_mpidr == intr->ArmMpidr) {
+ cpuid = i;
+ break;
+ }
+ }
+
+ if (cpuid == -1) {
+ /* pcpu not found. */
+ device_printf(sc->dev, "MADT: could not find pcpu, "
+ "ArmMpidr %lx\n", intr->ArmMpidr);
+ ctx->error = ENODEV;
+ return;
+ }
+
+ if (bootverbose)
+ device_printf(sc->dev, "MADT: cpu %d (mpidr %lu) irq %d "
+ "%s-triggered\n", cpuid, intr->ArmMpidr,
+ intr->PerformanceInterrupt,
+ (intr->Flags & ACPI_MADT_PERFORMANCE_IRQ_MODE) ?
+ "edge" : "level");
+
+ bus_set_resource(sc->dev, SYS_RES_IRQ, ctx->i,
+ intr->PerformanceInterrupt, 1);
+
+ sc->irq[ctx->i].res = bus_alloc_resource_any(sc->dev, SYS_RES_IRQ,
+ &rid, RF_ACTIVE | RF_SHAREABLE);
+ if (sc->irq[ctx->i].res == NULL) {
+ device_printf(sc->dev, "Failed to allocate IRQ %d\n", ctx->i);
+ ctx->error = ENXIO;
+ return;
+ }
+
+ /*
+ * BUS_CONFIG_INTR does nothing on arm64, so we manually set trigger
+ * mode.
+ */
+ data = rman_get_virtual(sc->irq[ctx->i].res);
+ KASSERT(data->type == INTR_MAP_DATA_ACPI, ("Wrong data type"));
+ ad = (struct intr_map_data_acpi *)data;
+ ad->trig = (intr->Flags & ACPI_MADT_PERFORMANCE_IRQ_MODE) ?
+ INTR_TRIGGER_EDGE : INTR_TRIGGER_LEVEL;
+ ad->pol = INTR_POLARITY_HIGH;
+
+ if (!intr_is_per_cpu(sc->irq[ctx->i].res))
+ sc->irq[ctx->i].cpuid = cpuid;
+
+ ctx->i++;
+}
+
+static void
+pmu_acpi_identify(driver_t *driver, device_t parent)
+{
+ device_t dev;
+
+ if (acpi_find_table(ACPI_SIG_MADT) == 0)
+ return;
+
+ dev = BUS_ADD_CHILD(parent, BUS_PASS_INTERRUPT + BUS_PASS_ORDER_LAST,
+ "pmu", -1);
+
+ if (dev == NULL)
+ device_printf(parent, "pmu: Unable to add pmu child\n");
+}
+
+static int
+pmu_acpi_probe(device_t dev)
+{
+
+ device_set_desc(dev, "Performance Monitoring Unit");
+
+ return (BUS_PROBE_NOWILDCARD);
+}
+
+static int
+pmu_acpi_attach(device_t dev)
+{
+ struct pmu_softc *sc;
+ struct madt_ctx ctx;
+ ACPI_TABLE_MADT *madt;
+ int i;
+
+ sc = device_get_softc(dev);
+ sc->dev = dev;
+
+ madt = acpi_map_table(acpi_find_table(ACPI_SIG_MADT), ACPI_SIG_MADT);
+ if (madt == NULL) {
+ device_printf(dev, "Unable to map the MADT table\n");
+ return (ENXIO);
+ }
+
+ /* We have to initialize cpuid to -1. */
+ for (i = 0; i < MAX_RLEN; i++)
+ sc->irq[i].cpuid = -1;
+
+ ctx.sc = sc;
+ ctx.i = 0;
+ ctx.error = 0;
+ acpi_walk_subtables(madt + 1, (char *)madt + madt->Header.Length,
+ madt_handler, &ctx);
+
+ acpi_unmap_table(madt);
+
+ if (ctx.error)
+ return (ctx.error);
+
+ return (pmu_attach(dev));
+}
+
+static device_method_t pmu_acpi_methods[] = {
+ DEVMETHOD(device_identify, pmu_acpi_identify),
+ DEVMETHOD(device_probe, pmu_acpi_probe),
+ DEVMETHOD(device_attach, pmu_acpi_attach),
+ DEVMETHOD_END,
+};
+
+DEFINE_CLASS_0(pmu, pmu_acpi_driver, pmu_acpi_methods,
+ sizeof(struct pmu_softc));
+
+static devclass_t pmu_acpi_devclass;
+
+DRIVER_MODULE(pmu, acpi, pmu_acpi_driver, pmu_acpi_devclass, 0, 0);
diff --git a/sys/conf/files.arm64 b/sys/conf/files.arm64
index 2d98568b3d9f..b363b800af67 100644
--- a/sys/conf/files.arm64
+++ b/sys/conf/files.arm64
@@ -22,6 +22,7 @@ arm/arm/gic_acpi.c optional acpi
arm/arm/gic_fdt.c optional fdt
arm/arm/gic_if.m standard
arm/arm/pmu.c standard
+arm/arm/pmu_acpi.c optional acpi
arm/arm/pmu_fdt.c optional fdt
arm64/acpica/acpi_iort.c optional acpi
arm64/acpica/acpi_machdep.c optional acpi