Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 16 May 2016 10:48:51 +0000 (UTC)
From:      Andrew Turner <andrew@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r299936 - in head/sys: arm64/arm64 arm64/include conf
Message-ID:  <201605161048.u4GAmpvf040770@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: andrew
Date: Mon May 16 10:48:51 2016
New Revision: 299936
URL: https://svnweb.freebsd.org/changeset/base/299936

Log:
  Add support for intrng to arm64. As the GICv3 drivers will need to be
  updated, and until further testing can be done, this is disabled for now.
  
  It is expected arm64 will switch to this interface, and the old interface
  will be removed before 11.0 is released.
  
  Obtained from:	ABT Systems Ltd
  Relnotes:	yes
  Sponsored by:	The FreeBSD Foundation

Modified:
  head/sys/arm64/arm64/autoconf.c
  head/sys/arm64/arm64/mp_machdep.c
  head/sys/arm64/arm64/nexus.c
  head/sys/arm64/include/intr.h
  head/sys/conf/files.arm64
  head/sys/conf/options.arm64

Modified: head/sys/arm64/arm64/autoconf.c
==============================================================================
--- head/sys/arm64/arm64/autoconf.c	Mon May 16 10:34:55 2016	(r299935)
+++ head/sys/arm64/arm64/autoconf.c	Mon May 16 10:48:51 2016	(r299936)
@@ -80,7 +80,13 @@ configure(void *dummy)
 static void
 configure_final(void *dummy)
 {
+
+#ifdef INTRNG
+	/* Enable interrupt reception on this CPU */
+	intr_enable();
+#else
 	arm_enable_intr();
+#endif
 	cninit_finish(); 
 
 	if (bootverbose)

Modified: head/sys/arm64/arm64/mp_machdep.c
==============================================================================
--- head/sys/arm64/arm64/mp_machdep.c	Mon May 16 10:34:55 2016	(r299935)
+++ head/sys/arm64/arm64/mp_machdep.c	Mon May 16 10:48:51 2016	(r299936)
@@ -1,5 +1,5 @@
 /*-
- * Copyright (c) 2015 The FreeBSD Foundation
+ * Copyright (c) 2015-2016 The FreeBSD Foundation
  * All rights reserved.
  *
  * This software was developed by Andrew Turner under
@@ -65,6 +65,29 @@ __FBSDID("$FreeBSD$");
 
 #include <dev/psci/psci.h>
 
+#ifdef INTRNG
+#include "pic_if.h"
+
+typedef void intr_ipi_send_t(void *, cpuset_t, u_int);
+typedef void intr_ipi_handler_t(void *);
+
+#define INTR_IPI_NAMELEN	(MAXCOMLEN + 1)
+struct intr_ipi {
+	intr_ipi_handler_t *	ii_handler;
+	void *			ii_handler_arg;
+	intr_ipi_send_t *	ii_send;
+	void *			ii_send_arg;
+	char			ii_name[INTR_IPI_NAMELEN];
+	u_long *		ii_count;
+};
+
+static struct intr_ipi ipi_sources[INTR_IPI_COUNT];
+
+static struct intr_ipi *intr_ipi_lookup(u_int);
+static void intr_pic_ipi_setup(u_int, const char *, intr_ipi_handler_t *,
+    void *);
+#endif /* INTRNG */
+
 boolean_t ofw_cpu_reg(phandle_t node, u_int, cell_t *);
 
 extern struct pcpu __pcpu[];
@@ -184,9 +207,18 @@ release_aps(void *dummy __unused)
 {
 	int cpu, i;
 
+#ifdef INTRNG
+	intr_pic_ipi_setup(IPI_AST, "ast", ipi_ast, NULL);
+	intr_pic_ipi_setup(IPI_PREEMPT, "preempt", ipi_preempt, NULL);
+	intr_pic_ipi_setup(IPI_RENDEZVOUS, "rendezvous", ipi_rendezvous, NULL);
+	intr_pic_ipi_setup(IPI_STOP, "stop", ipi_stop, NULL);
+	intr_pic_ipi_setup(IPI_STOP_HARD, "stop hard", ipi_stop, NULL);
+	intr_pic_ipi_setup(IPI_HARDCLOCK, "hardclock", ipi_hardclock, NULL);
+#else
 	/* Setup the IPI handler */
 	for (i = 0; i < INTR_IPI_COUNT; i++)
 		arm_setup_ipihandler(ipi_handler, i);
+#endif
 
 	atomic_store_rel_int(&aps_ready, 1);
 	/* Wake up the other CPUs */
@@ -214,7 +246,9 @@ void
 init_secondary(uint64_t cpu)
 {
 	struct pcpu *pcpup;
+#ifndef INTRNG
 	int i;
+#endif
 
 	pcpup = &__pcpu[cpu];
 	/*
@@ -241,11 +275,13 @@ init_secondary(uint64_t cpu)
 	 */
 	identify_cpu();
 
+#ifndef INTRNG
 	/* Configure the interrupt controller */
 	arm_init_secondary();
 
 	for (i = 0; i < INTR_IPI_COUNT; i++)
 		arm_unmask_ipi(i);
+#endif
 
 	/* Start per-CPU event timers. */
 	cpu_initclocks_ap();
@@ -270,6 +306,10 @@ init_secondary(uint64_t cpu)
 
 	mtx_unlock_spin(&ap_boot_mtx);
 
+#ifdef INTRNG
+	intr_pic_init_secondary();
+#endif
+
 	/* Enter the scheduler */
 	sched_throw(NULL);
 
@@ -277,6 +317,64 @@ init_secondary(uint64_t cpu)
 	/* NOTREACHED */
 }
 
+#ifdef INTRNG
+/*
+ *  Send IPI thru interrupt controller.
+ */
+static void
+pic_ipi_send(void *arg, cpuset_t cpus, u_int ipi)
+{
+
+	KASSERT(intr_irq_root_dev != NULL, ("%s: no root attached", __func__));
+	PIC_IPI_SEND(intr_irq_root_dev, arg, cpus, ipi);
+}
+
+/*
+ *  Setup IPI handler on interrupt controller.
+ *
+ *  Not SMP coherent.
+ */
+static void
+intr_pic_ipi_setup(u_int ipi, const char *name, intr_ipi_handler_t *hand,
+    void *arg)
+{
+	struct intr_irqsrc *isrc;
+	struct intr_ipi *ii;
+	int error;
+
+	KASSERT(intr_irq_root_dev != NULL, ("%s: no root attached", __func__));
+	KASSERT(hand != NULL, ("%s: ipi %u no handler", __func__, ipi));
+
+	error = PIC_IPI_SETUP(intr_irq_root_dev, ipi, &isrc);
+	if (error != 0)
+		return;
+
+	isrc->isrc_handlers++;
+
+	ii = intr_ipi_lookup(ipi);
+	KASSERT(ii->ii_count == NULL, ("%s: ipi %u reused", __func__, ipi));
+
+	ii->ii_handler = hand;
+	ii->ii_handler_arg = arg;
+	ii->ii_send = pic_ipi_send;
+	ii->ii_send_arg = isrc;
+	strlcpy(ii->ii_name, name, INTR_IPI_NAMELEN);
+	ii->ii_count = intr_ipi_setup_counters(name);
+}
+
+static void
+intr_ipi_send(cpuset_t cpus, u_int ipi)
+{
+	struct intr_ipi *ii;
+
+	ii = intr_ipi_lookup(ipi);
+	if (ii->ii_count == NULL)
+		panic("%s: not setup IPI %u", __func__, ipi);
+
+	ii->ii_send(ii->ii_send_arg, cpus, ipi);
+}
+#endif
+
 static void
 ipi_ast(void *dummy __unused)
 {
@@ -329,6 +427,7 @@ ipi_stop(void *dummy __unused)
 	CTR0(KTR_SMP, "IPI_STOP (restart)");
 }
 
+#ifndef INTRNG
 static int
 ipi_handler(void *arg)
 {
@@ -364,6 +463,7 @@ ipi_handler(void *arg)
 
 	return (FILTER_HANDLED);
 }
+#endif
 
 struct cpu_group *
 cpu_topo(void)
@@ -490,3 +590,149 @@ cpu_mp_setmaxid(void)
 	mp_ncpus = 1;
 	mp_maxid = 0;
 }
+
+#ifdef INTRNG
+/*
+ *  Lookup IPI source.
+ */
+static struct intr_ipi *
+intr_ipi_lookup(u_int ipi)
+{
+
+	if (ipi >= INTR_IPI_COUNT)
+		panic("%s: no such IPI %u", __func__, ipi);
+
+	return (&ipi_sources[ipi]);
+}
+
+/*
+ *  interrupt controller dispatch function for IPIs. It should
+ *  be called straight from the interrupt controller, when associated
+ *  interrupt source is learned. Or from anybody who has an interrupt
+ *  source mapped.
+ */
+void
+intr_ipi_dispatch(u_int ipi, struct trapframe *tf)
+{
+	void *arg;
+	struct intr_ipi *ii;
+
+	ii = intr_ipi_lookup(ipi);
+	if (ii->ii_count == NULL)
+		panic("%s: not setup IPI %u", __func__, ipi);
+
+	intr_ipi_increment_count(ii->ii_count, PCPU_GET(cpuid));
+
+	/*
+	 * Supply ipi filter with trapframe argument
+	 * if none is registered.
+	 */
+	arg = ii->ii_handler_arg != NULL ? ii->ii_handler_arg : tf;
+	ii->ii_handler(arg);
+}
+
+#ifdef notyet
+/*
+ *  Map IPI into interrupt controller.
+ *
+ *  Not SMP coherent.
+ */
+static int
+ipi_map(struct intr_irqsrc *isrc, u_int ipi)
+{
+	boolean_t is_percpu;
+	int error;
+
+	if (ipi >= INTR_IPI_COUNT)
+		panic("%s: no such IPI %u", __func__, ipi);
+
+	KASSERT(intr_irq_root_dev != NULL, ("%s: no root attached", __func__));
+
+	isrc->isrc_type = INTR_ISRCT_NAMESPACE;
+	isrc->isrc_nspc_type = INTR_IRQ_NSPC_IPI;
+	isrc->isrc_nspc_num = ipi_next_num;
+
+	error = PIC_REGISTER(intr_irq_root_dev, isrc, &is_percpu);
+	if (error == 0) {
+		isrc->isrc_dev = intr_irq_root_dev;
+		ipi_next_num++;
+	}
+	return (error);
+}
+
+/*
+ *  Setup IPI handler to interrupt source.
+ *
+ *  Note that there could be more ways how to send and receive IPIs
+ *  on a platform like fast interrupts for example. In that case,
+ *  one can call this function with ASIF_NOALLOC flag set and then
+ *  call intr_ipi_dispatch() when appropriate.
+ *
+ *  Not SMP coherent.
+ */
+int
+intr_ipi_set_handler(u_int ipi, const char *name, intr_ipi_filter_t *filter,
+    void *arg, u_int flags)
+{
+	struct intr_irqsrc *isrc;
+	int error;
+
+	if (filter == NULL)
+		return(EINVAL);
+
+	isrc = intr_ipi_lookup(ipi);
+	if (isrc->isrc_ipifilter != NULL)
+		return (EEXIST);
+
+	if ((flags & AISHF_NOALLOC) == 0) {
+		error = ipi_map(isrc, ipi);
+		if (error != 0)
+			return (error);
+	}
+
+	isrc->isrc_ipifilter = filter;
+	isrc->isrc_arg = arg;
+	isrc->isrc_handlers = 1;
+	isrc->isrc_count = intr_ipi_setup_counters(name);
+	isrc->isrc_index = 0; /* it should not be used in IPI case */
+
+	if (isrc->isrc_dev != NULL) {
+		PIC_ENABLE_INTR(isrc->isrc_dev, isrc);
+		PIC_ENABLE_SOURCE(isrc->isrc_dev, isrc);
+	}
+	return (0);
+}
+#endif
+
+/* Sending IPI */
+void
+ipi_all_but_self(u_int ipi)
+{
+	cpuset_t cpus;
+
+	cpus = all_cpus;
+	CPU_CLR(PCPU_GET(cpuid), &cpus);
+	CTR2(KTR_SMP, "%s: ipi: %x", __func__, ipi);
+	intr_ipi_send(cpus, ipi);
+}
+
+void
+ipi_cpu(int cpu, u_int ipi)
+{
+	cpuset_t cpus;
+
+	CPU_ZERO(&cpus);
+	CPU_SET(cpu, &cpus);
+
+	CTR3(KTR_SMP, "%s: cpu: %d, ipi: %x", __func__, cpu, ipi);
+	intr_ipi_send(cpus, ipi);
+}
+
+void
+ipi_selected(cpuset_t cpus, u_int ipi)
+{
+
+	CTR2(KTR_SMP, "%s: ipi: %x", __func__, ipi);
+	intr_ipi_send(cpus, ipi);
+}
+#endif /* INTRNG */

Modified: head/sys/arm64/arm64/nexus.c
==============================================================================
--- head/sys/arm64/arm64/nexus.c	Mon May 16 10:34:55 2016	(r299935)
+++ head/sys/arm64/arm64/nexus.c	Mon May 16 10:48:51 2016	(r299936)
@@ -271,7 +271,13 @@ nexus_config_intr(device_t dev, int irq,
     enum intr_polarity pol)
 {
 
+#ifdef INTRNG
+	/* TODO: This is wrong, it's needed for ACPI */
+	device_printf(dev, "bus_config_intr is obsolete and not supported!\n");
+	return (EOPNOTSUPP);
+#else
 	return (intr_irq_config(irq, trig, pol));
+#endif
 }
 
 static int
@@ -288,8 +294,12 @@ nexus_setup_intr(device_t dev, device_t 
 	if (error)
 		return (error);
 
+#ifdef INTRNG
+	error = intr_setup_irq(child, res, filt, intr, arg, flags, cookiep);
+#else
 	error = arm_setup_intr(device_get_nameunit(child), filt, intr,
 	    arg, rman_get_start(res), flags, cookiep);
+#endif
 
 	return (error);
 }
@@ -298,7 +308,11 @@ static int
 nexus_teardown_intr(device_t dev, device_t child, struct resource *r, void *ih)
 {
 
+#ifdef INTRNG
+	return (intr_teardown_irq(child, r, ih));
+#else
 	return (intr_irq_remove_handler(child, rman_get_start(r), ih));
+#endif
 }
 
 #ifdef SMP
@@ -306,7 +320,11 @@ static int
 nexus_bind_intr(device_t dev, device_t child, struct resource *irq, int cpu)
 {
 
+#ifdef INTRNG
+	return (intr_bind_irq(child, irq, cpu));
+#else
 	return (intr_irq_bind(rman_get_start(irq), cpu));
+#endif
 }
 #endif
 
@@ -429,6 +447,9 @@ static int
 nexus_ofw_map_intr(device_t dev, device_t child, phandle_t iparent, int icells,
     pcell_t *intr)
 {
+#ifdef INTRNG
+	return (intr_fdt_map_irq(iparent, intr, icells));
+#else
 	int irq;
 
 	if (icells == 3) {
@@ -441,6 +462,7 @@ nexus_ofw_map_intr(device_t dev, device_
 		irq = intr[0];
 
 	return (irq);
+#endif
 }
 #endif
 

Modified: head/sys/arm64/include/intr.h
==============================================================================
--- head/sys/arm64/include/intr.h	Mon May 16 10:34:55 2016	(r299935)
+++ head/sys/arm64/include/intr.h	Mon May 16 10:48:51 2016	(r299936)
@@ -29,6 +29,28 @@
 #ifndef _MACHINE_INTR_H_
 #define	_MACHINE_INTR_H_
 
+#ifdef INTRNG
+
+#ifdef FDT
+#include <dev/ofw/openfirm.h>
+#endif
+
+#include <sys/intr.h>
+
+#ifndef NIRQ
+#define	NIRQ		1024	/* XXX - It should be an option. */
+#endif
+
+static inline void
+arm_irq_memory_barrier(uintptr_t irq)
+{
+}
+
+#ifdef SMP
+void intr_ipi_dispatch(u_int, struct trapframe *);
+#endif
+
+#else
 int	intr_irq_config(u_int, enum intr_trigger, enum intr_polarity);
 void	intr_irq_handler(struct trapframe *);
 int	intr_irq_remove_handler(device_t, u_int, void *);
@@ -55,5 +77,6 @@ void	arm_init_secondary(void);
 void	arm_setup_ipihandler(driver_filter_t *, u_int);
 void	arm_unmask_ipi(u_int);
 #endif
+#endif
 
 #endif	/* _MACHINE_INTR_H */

Modified: head/sys/conf/files.arm64
==============================================================================
--- head/sys/conf/files.arm64	Mon May 16 10:34:55 2016	(r299935)
+++ head/sys/conf/files.arm64	Mon May 16 10:48:51 2016	(r299936)
@@ -1,5 +1,6 @@
 # $FreeBSD$
 arm/arm/generic_timer.c		standard
+arm/arm/gic.c			optional	intrng
 arm/arm/pmu.c			standard
 arm64/acpica/acpi_machdep.c	optional	acpi
 arm64/acpica/OsdEnvironment.c	optional	acpi
@@ -24,14 +25,14 @@ arm64/arm64/disassem.c		optional	ddb
 arm64/arm64/dump_machdep.c	standard
 arm64/arm64/elf_machdep.c	standard
 arm64/arm64/exception.S		standard
-arm64/arm64/gic.c		standard
-arm64/arm64/gic_acpi.c		optional	acpi
-arm64/arm64/gic_fdt.c		optional	fdt
-arm64/arm64/gic_v3.c		standard
-arm64/arm64/gic_v3_fdt.c	optional	fdt
-arm64/arm64/gic_v3_its.c	standard
+arm64/arm64/gic.c		optional	!intrng
+arm64/arm64/gic_acpi.c		optional	!intrng acpi
+arm64/arm64/gic_fdt.c		optional	!intrng fdt
+arm64/arm64/gic_v3.c		optional	!intrng
+arm64/arm64/gic_v3_fdt.c	optional	!intrng fdt
+arm64/arm64/gic_v3_its.c	optional	!intrng
 arm64/arm64/identcpu.c		standard
-arm64/arm64/intr_machdep.c	standard
+arm64/arm64/intr_machdep.c	optional	!intrng
 arm64/arm64/in_cksum.c		optional	inet | inet6
 arm64/arm64/locore.S		standard	no-obj
 arm64/arm64/machdep.c		standard
@@ -40,7 +41,7 @@ arm64/arm64/minidump_machdep.c	standard
 arm64/arm64/mp_machdep.c	optional	smp
 arm64/arm64/nexus.c		standard
 arm64/arm64/ofw_machdep.c	optional	fdt
-arm64/arm64/pic_if.m		standard
+arm64/arm64/pic_if.m		optional	!intrng
 arm64/arm64/pmap.c		standard
 arm64/arm64/stack_machdep.c	optional	ddb | stack
 arm64/arm64/support.S		standard
@@ -83,7 +84,10 @@ dev/vnic/thunder_mdio_fdt.c	optional	vni
 dev/vnic/thunder_mdio.c		optional	vnic
 dev/vnic/lmac_if.m		optional	vnic
 kern/kern_clocksource.c		standard
+kern/msi_if.m			optional	intrng
+kern/pic_if.m			optional	intrng
 kern/subr_devmap.c		standard
+kern/subr_intr.c		optional	intrng
 libkern/bcmp.c			standard
 libkern/ffs.c			standard
 libkern/ffsl.c			standard

Modified: head/sys/conf/options.arm64
==============================================================================
--- head/sys/conf/options.arm64	Mon May 16 10:34:55 2016	(r299935)
+++ head/sys/conf/options.arm64	Mon May 16 10:48:51 2016	(r299936)
@@ -1,6 +1,7 @@
 # $FreeBSD$
 
 ARM64				opt_global.h
+INTRNG				opt_global.h
 SOCDEV_PA			opt_global.h
 SOCDEV_VA			opt_global.h
 THUNDERX_PASS_1_1_ERRATA	opt_global.h



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201605161048.u4GAmpvf040770>