From owner-dev-commits-src-all@freebsd.org Tue Sep 14 10:42:36 2021 Return-Path: Delivered-To: dev-commits-src-all@mailman.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mailman.nyi.freebsd.org (Postfix) with ESMTP id 83E05665FB8; Tue, 14 Sep 2021 10:42:36 +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 4H80Km01pvz3GPK; Tue, 14 Sep 2021 10:42:35 +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 B2237195CA; Tue, 14 Sep 2021 10:42:35 +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 18EAgZUL041639; Tue, 14 Sep 2021 10:42:35 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.16.1/8.16.1/Submit) id 18EAgZX9041638; Tue, 14 Sep 2021 10:42:35 GMT (envelope-from git) Date: Tue, 14 Sep 2021 10:42:35 GMT Message-Id: <202109141042.18EAgZX9041638@gitrepo.freebsd.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org From: Andrew Turner Subject: git: e4d89a633e3b - main - Add support for gicv2m as a child of gicv3 MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: andrew X-Git-Repository: src X-Git-Refname: refs/heads/main X-Git-Reftype: branch X-Git-Commit: e4d89a633e3b31ec1319e3238abceee2048996c4 Auto-Submitted: auto-generated X-BeenThere: dev-commits-src-all@freebsd.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: Commit messages for all branches of the src repository List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 14 Sep 2021 10:42:36 -0000 The branch main has been updated by andrew: URL: https://cgit.FreeBSD.org/src/commit/?id=e4d89a633e3b31ec1319e3238abceee2048996c4 commit e4d89a633e3b31ec1319e3238abceee2048996c4 Author: Andrew Turner AuthorDate: 2021-09-01 09:41:14 +0000 Commit: Andrew Turner CommitDate: 2021-09-14 07:24:52 +0000 Add support for gicv2m as a child of gicv3 On some systems, e.g. Parallels set to host a Linux VM under an M1 Mac, there is a GICv2m as a child of the GICv3. We previously assumed the GICv2m was always a child of a GICv2. Fix this by adding the needed support to the GICv3 driver. PR: 258136 Reported by: trasz Sponsored by: The FreeBSD Foundation Differential Revision: https://reviews.freebsd.org/D31768 --- sys/arm64/arm64/gic_v3.c | 90 ++++++++++++++++++++++++++++++++++++++++---- sys/arm64/arm64/gic_v3_fdt.c | 2 +- 2 files changed, 83 insertions(+), 9 deletions(-) diff --git a/sys/arm64/arm64/gic_v3.c b/sys/arm64/arm64/gic_v3.c index 3e7cd30140eb..a53d0b272723 100644 --- a/sys/arm64/arm64/gic_v3.c +++ b/sys/arm64/arm64/gic_v3.c @@ -78,6 +78,7 @@ __FBSDID("$FreeBSD$"); static bus_get_domain_t gic_v3_get_domain; static bus_read_ivar_t gic_v3_read_ivar; +static bus_write_ivar_t gic_v3_write_ivar; static pic_disable_intr_t gic_v3_disable_intr; static pic_enable_intr_t gic_v3_enable_intr; @@ -113,6 +114,7 @@ static device_method_t gic_v3_methods[] = { /* Bus interface */ DEVMETHOD(bus_get_domain, gic_v3_get_domain), DEVMETHOD(bus_read_ivar, gic_v3_read_ivar), + DEVMETHOD(bus_write_ivar, gic_v3_write_ivar), /* Interrupt controller interface */ DEVMETHOD(pic_disable_intr, gic_v3_disable_intr), @@ -242,6 +244,33 @@ gic_r_write_8(device_t dev, bus_size_t offset, uint64_t val) bus_write_8(rdist, offset, val); } +static void +gic_v3_reserve_msi_range(device_t dev, u_int start, u_int count) +{ + struct gic_v3_softc *sc; + int i; + + sc = device_get_softc(dev); + + KASSERT((start + count) < sc->gic_nirqs, + ("%s: Trying to allocate too many MSI IRQs: %d + %d > %d", __func__, + start, count, sc->gic_nirqs)); + for (i = 0; i < count; i++) { + KASSERT(sc->gic_irqs[start + i].gi_isrc.isrc_handlers == 0, + ("%s: MSI interrupt %d already has a handler", __func__, + count + i)); + KASSERT(sc->gic_irqs[start + i].gi_pol == INTR_POLARITY_CONFORM, + ("%s: MSI interrupt %d already has a polarity", __func__, + count + i)); + KASSERT(sc->gic_irqs[start + i].gi_trig == INTR_TRIGGER_CONFORM, + ("%s: MSI interrupt %d already has a trigger", __func__, + count + i)); + sc->gic_irqs[start + i].gi_pol = INTR_POLARITY_HIGH; + sc->gic_irqs[start + i].gi_trig = INTR_TRIGGER_EDGE; + sc->gic_irqs[start + i].gi_flags |= GI_FLAG_MSI; + } +} + /* * Device interface. */ @@ -332,15 +361,10 @@ gic_v3_attach(device_t dev) } } + mtx_init(&sc->gic_mbi_mtx, "GICv3 mbi lock", NULL, MTX_DEF); if (sc->gic_mbi_start > 0) { - /* Reserve these interrupts for MSI/MSI-X use */ - for (irq = sc->gic_mbi_start; irq <= sc->gic_mbi_end; irq++) { - sc->gic_irqs[irq].gi_pol = INTR_POLARITY_HIGH; - sc->gic_irqs[irq].gi_trig = INTR_TRIGGER_EDGE; - sc->gic_irqs[irq].gi_flags |= GI_FLAG_MSI; - } - - mtx_init(&sc->gic_mbi_mtx, "GICv3 mbi lock", NULL, MTX_DEF); + gic_v3_reserve_msi_range(dev, sc->gic_mbi_start, + sc->gic_mbi_end - sc->gic_mbi_start); if (bootverbose) { device_printf(dev, "using spi %u to %u\n", sc->gic_mbi_start, @@ -442,6 +466,56 @@ gic_v3_read_ivar(device_t dev, device_t child, int which, uintptr_t *result) KASSERT(sc->gic_bus <= GIC_BUS_MAX, ("gic_v3_read_ivar: Invalid bus type %u", sc->gic_bus)); *result = sc->gic_bus; + return (0); + case GIC_IVAR_MBI_START: + *result = sc->gic_mbi_start; + return (0); + case GIC_IVAR_MBI_COUNT: + *result = sc->gic_mbi_end - sc->gic_mbi_start; + return (0); + } + + return (ENOENT); +} + +static int +gic_v3_write_ivar(device_t dev, device_t child, int which, uintptr_t value) +{ + struct gic_v3_softc *sc; + + sc = device_get_softc(dev); + + switch(which) { + case GICV3_IVAR_NIRQS: + case GICV3_IVAR_REDIST: + case GIC_IVAR_HW_REV: + case GIC_IVAR_BUS: + return (EINVAL); + case GIC_IVAR_MBI_START: + /* + * GIC_IVAR_MBI_START must be set once and first. This allows + * us to reserve the registers when GIC_IVAR_MBI_COUNT is set. + */ + MPASS(sc->gic_mbi_start == 0); + MPASS(sc->gic_mbi_end == 0); + MPASS(value >= GIC_FIRST_SPI); + MPASS(value < sc->gic_nirqs); + + sc->gic_mbi_start = value; + return (0); + case GIC_IVAR_MBI_COUNT: + MPASS(sc->gic_mbi_start != 0); + MPASS(sc->gic_mbi_end == 0); + MPASS(value >= sc->gic_mbi_start); + MPASS(value >= GIC_FIRST_SPI); + + sc->gic_mbi_end = value - sc->gic_mbi_start; + + MPASS(sc->gic_mbi_end <= sc->gic_nirqs); + + /* Reserve these interrupts for MSI/MSI-X use */ + gic_v3_reserve_msi_range(dev, sc->gic_mbi_start, value); + return (0); } diff --git a/sys/arm64/arm64/gic_v3_fdt.c b/sys/arm64/arm64/gic_v3_fdt.c index d2c0611c9167..65d7ca7e374d 100644 --- a/sys/arm64/arm64/gic_v3_fdt.c +++ b/sys/arm64/arm64/gic_v3_fdt.c @@ -143,7 +143,7 @@ gic_v3_fdt_attach(device_t dev) if (ret % 2 == 0) { /* Limit to a single range for now. */ sc->gic_mbi_start = mbi_ranges[0]; - sc->gic_mbi_end = mbi_ranges[0] + mbi_ranges[1] - 1; + sc->gic_mbi_end = mbi_ranges[0] + mbi_ranges[1]; } else { if (bootverbose) device_printf(dev, "Malformed mbi-ranges property\n");