From owner-svn-src-all@freebsd.org Mon Apr 4 17:04:34 2016 Return-Path: Delivered-To: svn-src-all@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id 6D2CEB03239; Mon, 4 Apr 2016 17:04:34 +0000 (UTC) (envelope-from andrew@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id 4868B162C; Mon, 4 Apr 2016 17:04:34 +0000 (UTC) (envelope-from andrew@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id u34H4XKw040672; Mon, 4 Apr 2016 17:04:33 GMT (envelope-from andrew@FreeBSD.org) Received: (from andrew@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id u34H4XK6040670; Mon, 4 Apr 2016 17:04:33 GMT (envelope-from andrew@FreeBSD.org) Message-Id: <201604041704.u34H4XK6040670@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: andrew set sender to andrew@FreeBSD.org using -f From: Andrew Turner Date: Mon, 4 Apr 2016 17:04:33 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r297561 - in head/sys: arm/arm arm64/arm64 X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 04 Apr 2016 17:04:34 -0000 Author: andrew Date: Mon Apr 4 17:04:33 2016 New Revision: 297561 URL: https://svnweb.freebsd.org/changeset/base/297561 Log: Add a table to map from the FreeBSD CPUID space to the GIC CPUID space. On many SoCs these two are the same, however there is no requirement for this to be the case, e.g. on the ARM Juno we boot on what the GIC thinks of as CPU 2, but FreeBSD numbers it CPU 0. Obtained from: ABT Systems Ltd Sponsored by: The FreeBSD Foundation Modified: head/sys/arm/arm/gic.c head/sys/arm64/arm64/gic.c Modified: head/sys/arm/arm/gic.c ============================================================================== --- head/sys/arm/arm/gic.c Mon Apr 4 16:41:35 2016 (r297560) +++ head/sys/arm/arm/gic.c Mon Apr 4 17:04:33 2016 (r297561) @@ -84,6 +84,7 @@ __FBSDID("$FreeBSD$"); #define GICD_ITARGETSR(n) (0x0800 + ((n) * 4)) /* v1 ICDIPTR */ #define GICD_ICFGR(n) (0x0C00 + ((n) * 4)) /* v1 ICDICFR */ #define GICD_SGIR(n) (0x0F00 + ((n) * 4)) /* v1 ICDSGIR */ +#define GICD_SGI_TARGET_SHIFT 16 /* CPU Registers */ #define GICC_CTLR 0x0000 /* v1 ICCICR */ @@ -165,6 +166,8 @@ static struct resource_spec arm_gic_spec { -1, 0 } }; +static u_int arm_gic_map[MAXCPU]; + static struct arm_gic_softc *gic_sc = NULL; #define gic_c_read_4(_sc, _reg) \ @@ -224,6 +227,29 @@ gic_irq_mask(struct arm_gic_softc *sc, u } #endif +static uint8_t +gic_cpu_mask(struct arm_gic_softc *sc) +{ + uint32_t mask; + int i; + + /* Read the current cpuid mask by reading ITARGETSR{0..7} */ + for (i = 0; i < 8; i++) { + mask = gic_d_read_4(sc, GICD_ITARGETSR(i)); + if (mask != 0) + break; + } + /* No mask found, assume we are on CPU interface 0 */ + if (mask == 0) + return (1); + + /* Collect the mask in the lower byte */ + mask |= mask >> 16; + mask |= mask >> 8; + + return (mask); +} + #ifdef SMP #ifdef ARM_INTRNG static void @@ -233,6 +259,9 @@ arm_gic_init_secondary(device_t dev) struct intr_irqsrc *isrc; u_int irq; + /* Set the mask so we can find this CPU to send it IPIs */ + arm_gic_map[PCPU_GET(cpuid)] = gic_cpu_mask(sc); + for (irq = 0; irq < sc->nirqs; irq += 4) gic_d_write_4(sc, GICD_IPRIORITYR(irq >> 2), 0); @@ -280,6 +309,9 @@ arm_gic_init_secondary(device_t dev) struct arm_gic_softc *sc = device_get_softc(dev); int i; + /* Set the mask so we can find this CPU to send it IPIs */ + arm_gic_map[PCPU_GET(cpuid)] = gic_cpu_mask(sc); + for (i = 0; i < sc->nirqs; i += 4) gic_d_write_4(sc, GICD_IPRIORITYR(i >> 2), 0); @@ -490,20 +522,11 @@ arm_gic_attach(device_t dev) gic_d_write_4(sc, GICD_ICENABLER(i >> 5), 0xFFFFFFFF); } - /* Read the current cpuid mask by reading ITARGETSR{0..7} */ - for (i = 0; i < 8; i++) { - mask = gic_d_read_4(sc, GICD_ITARGETSR(i)); - if (mask != 0) - break; - } - /* No mask found, assume we are on CPU interface 0 */ - if (mask == 0) - mask = 1; - - /* Collect the mask in the lower byte */ - mask |= mask >> 16; - mask |= mask >> 8; - /* Distribute this back to the upper bytes */ + /* Find the current cpu mask */ + mask = gic_cpu_mask(sc); + /* Set the mask so we can find this CPU to send it IPIs */ + arm_gic_map[PCPU_GET(cpuid)] = mask; + /* Set all four targets to this cpu */ mask |= mask << 8; mask |= mask << 16; @@ -985,7 +1008,7 @@ arm_gic_ipi_send(device_t dev, struct in for (i = 0; i < MAXCPU; i++) if (CPU_ISSET(i, &cpus)) - val |= 1 << (16 + i); + val |= arm_gic_map[i] << GICD_SGI_TARGET_SHIFT; gic_d_write_4(sc, GICD_SGIR(0), val | gi->gi_irq); } @@ -1113,7 +1136,7 @@ arm_gic_ipi_send(device_t dev, cpuset_t for (i = 0; i < MAXCPU; i++) if (CPU_ISSET(i, &cpus)) - val |= 1 << (16 + i); + val |= arm_gic_map[i] << GICD_SGI_TARGET_SHIFT; gic_d_write_4(sc, GICD_SGIR(0), val | ipi); } Modified: head/sys/arm64/arm64/gic.c ============================================================================== --- head/sys/arm64/arm64/gic.c Mon Apr 4 16:41:35 2016 (r297560) +++ head/sys/arm64/arm64/gic.c Mon Apr 4 17:04:33 2016 (r297561) @@ -75,6 +75,7 @@ __FBSDID("$FreeBSD$"); #define GICD_ITARGETSR(n) (0x0800 + ((n) * 4)) /* v1 ICDIPTR */ #define GICD_ICFGR(n) (0x0C00 + ((n) * 4)) /* v1 ICDICFR */ #define GICD_SGIR(n) (0x0F00 + ((n) * 4)) /* v1 ICDSGIR */ +#define GICD_SGI_TARGET_SHIFT 16 /* CPU Registers */ #define GICC_CTLR 0x0000 /* v1 ICCICR */ @@ -108,6 +109,8 @@ static struct resource_spec arm_gic_spec { -1, 0 } }; +static u_int arm_gic_map[MAXCPU]; + static struct arm_gic_softc *arm_gic_sc = NULL; #define gic_c_read_4(_sc, _reg) \ @@ -124,6 +127,29 @@ static pic_eoi_t gic_eoi; static pic_mask_t gic_mask_irq; static pic_unmask_t gic_unmask_irq; +static uint8_t +gic_cpu_mask(struct arm_gic_softc *sc) +{ + uint32_t mask; + int i; + + /* Read the current cpuid mask by reading ITARGETSR{0..7} */ + for (i = 0; i < 8; i++) { + mask = gic_d_read_4(sc, GICD_ITARGETSR(i)); + if (mask != 0) + break; + } + /* No mask found, assume we are on CPU interface 0 */ + if (mask == 0) + return (1); + + /* Collect the mask in the lower byte */ + mask |= mask >> 16; + mask |= mask >> 8; + + return (mask); +} + #ifdef SMP static void gic_init_secondary(device_t dev) @@ -131,6 +157,9 @@ gic_init_secondary(device_t dev) struct arm_gic_softc *sc = device_get_softc(dev); int i; + /* Set the mask so we can find this CPU to send it IPIs */ + arm_gic_map[PCPU_GET(cpuid)] = gic_cpu_mask(sc); + for (i = 0; i < sc->nirqs; i += 4) gic_d_write_4(sc, GICD_IPRIORITYR(i >> 2), 0); @@ -212,20 +241,11 @@ arm_gic_attach(device_t dev) gic_d_write_4(sc, GICD_ICENABLER(i >> 5), 0xFFFFFFFF); } - /* Read the current cpuid mask by reading ITARGETSR{0..7} */ - for (i = 0; i < 8; i++) { - mask = gic_d_read_4(sc, GICD_ITARGETSR(i)); - if (mask != 0) - break; - } - /* No mask found, assume we are on CPU interface 0 */ - if (mask == 0) - mask = 1; - - /* Collect the mask in the lower byte */ - mask |= mask >> 16; - mask |= mask >> 8; - /* Distribute this back to the upper bytes */ + /* Find the current cpu mask */ + mask = gic_cpu_mask(sc); + /* Set the mask so we can find this CPU to send it IPIs */ + arm_gic_map[PCPU_GET(cpuid)] = mask; + /* Set all four targets to this cpu */ mask |= mask << 8; mask |= mask << 16; @@ -317,7 +337,7 @@ gic_ipi_send(device_t dev, cpuset_t cpus for (i = 0; i < MAXCPU; i++) if (CPU_ISSET(i, &cpus)) - val |= 1 << (16 + i); + val |= arm_gic_map[i] << GICD_SGI_TARGET_SHIFT; gic_d_write_4(sc, GICD_SGIR(0), val | ipi); }