svn commit: r296138 - in head/sys: arm/arm arm/include kern sys

Adrian Chadd adrian.chadd at gmail.com
Sun Feb 28 00:57:05 UTC 2016


hi,

I think this was mostly shared with kan's MIPS work on the CI20 as the
IPI stuff via the gic is effectively the same.

Can we make this (again) something we can share, but optionally?


-a


On 27 February 2016 at 04:03, Svatopluk Kraus <skra at freebsd.org> wrote:
> Author: skra
> Date: Sat Feb 27 12:03:07 2016
> New Revision: 296138
> URL: https://svnweb.freebsd.org/changeset/base/296138
>
> Log:
>   Move IPI related parts back to (ARM) machine specific file now, when
>   the interrupt framework is also going to be used by another (MIPS)
>   architecture. IPI implementations may vary much across different
>   architectures.
>
>   An IPI implementation should still define INTR_IPI_COUNT and use
>   intr_ipi_setup_counters() to setup IPI counters which are inside of
>   intrcnt[] and intrnames[] arrays. Those are used for sysctl and ddb.
>   Then, intr_ipi_increment_count() should be used to increment obtained
>   counter.
>
>   Reviewed by:  imp
>   Differential Revision:        https://reviews.freebsd.org/D5459
>
> Modified:
>   head/sys/arm/arm/machdep_intr.c
>   head/sys/arm/include/intr.h
>   head/sys/kern/subr_intr.c
>   head/sys/sys/intr.h
>
> Modified: head/sys/arm/arm/machdep_intr.c
> ==============================================================================
> --- head/sys/arm/arm/machdep_intr.c     Sat Feb 27 03:38:01 2016        (r296137)
> +++ head/sys/arm/arm/machdep_intr.c     Sat Feb 27 12:03:07 2016        (r296138)
> @@ -52,11 +52,22 @@ __FBSDID("$FreeBSD$");
>  #include <sys/conf.h>
>  #include <sys/pmc.h>
>  #include <sys/pmckern.h>
> +#include <sys/smp.h>
>
>  #include <machine/atomic.h>
>  #include <machine/bus.h>
>  #include <machine/intr.h>
>  #include <machine/cpu.h>
> +#include <machine/smp.h>
> +
> +#ifdef ARM_INTRNG
> +#include "pic_if.h"
> +
> +#ifdef SMP
> +static struct intr_irqsrc ipi_sources[INTR_IPI_COUNT];
> +static u_int ipi_next_num;
> +#endif
> +#endif
>
>  /*
>   * arm_irq_memory_barrier()
> @@ -121,3 +132,127 @@ arm_irq_memory_barrier(uintptr_t irq)
>         cpu_l2cache_drain_writebuf();
>  }
>
> +#ifdef ARM_INTRNG
> +#ifdef SMP
> +/*
> + *  Lookup IPI source.
> + */
> +static struct intr_irqsrc *
> +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(struct intr_irqsrc *isrc, struct trapframe *tf)
> +{
> +       void *arg;
> +
> +       KASSERT(isrc != NULL, ("%s: no source", __func__));
> +
> +       intr_ipi_increment_count(isrc->isrc_count, PCPU_GET(cpuid));
> +
> +       /*
> +        * Supply ipi filter with trapframe argument
> +        * if none is registered.
> +        */
> +       arg = isrc->isrc_arg != NULL ? isrc->isrc_arg : tf;
> +       isrc->isrc_ipifilter(arg);
> +}
> +
> +/*
> + *  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);
> +}
> +
> +/*
> + *  Send IPI thru interrupt controller.
> + */
> +void
> +pic_ipi_send(cpuset_t cpus, u_int ipi)
> +{
> +       struct intr_irqsrc *isrc;
> +
> +       isrc = intr_ipi_lookup(ipi);
> +
> +       KASSERT(intr_irq_root_dev != NULL, ("%s: no root attached", __func__));
> +       PIC_IPI_SEND(intr_irq_root_dev, isrc, cpus);
> +}
> +#endif
> +#endif
>
> Modified: head/sys/arm/include/intr.h
> ==============================================================================
> --- head/sys/arm/include/intr.h Sat Feb 27 03:38:01 2016        (r296137)
> +++ head/sys/arm/include/intr.h Sat Feb 27 12:03:07 2016        (r296138)
> @@ -51,6 +51,15 @@
>
>  #include <sys/intr.h>
>
> +#ifdef SMP
> +void intr_ipi_dispatch(struct intr_irqsrc *isrc, struct trapframe *tf);
> +
> +#define AISHF_NOALLOC  0x0001
> +
> +int intr_ipi_set_handler(u_int ipi, const char *name, intr_ipi_filter_t *filter,
> +    void *arg, u_int flags);
> +#endif
> +
>  #else /* ARM_INTRNG */
>
>  /* XXX move to std.* files? */
>
> Modified: head/sys/kern/subr_intr.c
> ==============================================================================
> --- head/sys/kern/subr_intr.c   Sat Feb 27 03:38:01 2016        (r296137)
> +++ head/sys/kern/subr_intr.c   Sat Feb 27 12:03:07 2016        (r296138)
> @@ -89,7 +89,7 @@ void intr_irq_handler(struct trapframe *
>
>  /* Root interrupt controller stuff. */
>  static struct intr_irqsrc *irq_root_isrc;
> -static device_t irq_root_dev;
> +device_t intr_irq_root_dev;
>  static intr_irq_filter_t *irq_root_filter;
>  static void *irq_root_arg;
>  static u_int irq_root_ipicount;
> @@ -115,9 +115,6 @@ u_int irq_next_free;
>
>  #ifdef SMP
>  static boolean_t irq_assign_cpu = FALSE;
> -
> -static struct intr_irqsrc ipi_sources[INTR_IPI_COUNT];
> -static u_int ipi_next_num;
>  #endif
>
>  /*
> @@ -239,36 +236,20 @@ isrc_setup_counters(struct intr_irqsrc *
>
>  #ifdef SMP
>  /*
> - *  Virtualization for interrupt source IPI counter increment.
> - */
> -static inline void
> -isrc_increment_ipi_count(struct intr_irqsrc *isrc, u_int cpu)
> -{
> -
> -       isrc->isrc_count[cpu]++;
> -}
> -
> -/*
>   *  Virtualization for interrupt source IPI counters setup.
>   */
> -static void
> -isrc_setup_ipi_counters(struct intr_irqsrc *isrc, const char *name)
> +u_long *
> +intr_ipi_setup_counters(const char *name)
>  {
>         u_int index, i;
>         char str[INTRNAME_LEN];
>
>         index = atomic_fetchadd_int(&intrcnt_index, MAXCPU);
> -       isrc->isrc_index = index;
> -       isrc->isrc_count = &intrcnt[index];
> -
>         for (i = 0; i < MAXCPU; i++) {
> -               /*
> -                * We do not expect any race in IPI case here,
> -                * so locking is not needed.
> -                */
>                 snprintf(str, INTRNAME_LEN, "cpu%d:%s", i, name);
>                 intrcnt_setname(str, index + i);
>         }
> +       return (&intrcnt[index]);
>  }
>  #endif
>
> @@ -679,7 +660,7 @@ intr_isrc_assign_cpu(void *arg, int cpu)
>         struct intr_irqsrc *isrc = arg;
>         int error;
>
> -       if (isrc->isrc_dev != irq_root_dev)
> +       if (isrc->isrc_dev != intr_irq_root_dev)
>                 return (EINVAL);
>
>         mtx_lock(&isrc_table_lock);
> @@ -926,7 +907,7 @@ intr_pic_claim_root(device_t dev, intptr
>          * Note that we further suppose that there is not threaded interrupt
>          * routine (handler) on the root. See intr_irq_handler().
>          */
> -       if (irq_root_dev != NULL) {
> +       if (intr_irq_root_dev != NULL) {
>                 device_printf(dev, "another root already set\n");
>                 return (EBUSY);
>         }
> @@ -949,7 +930,7 @@ intr_pic_claim_root(device_t dev, intptr
>                 device_printf(dev, "failed to install root pic handler\n");
>                 return (error);
>         }
> -       irq_root_dev = dev;
> +       intr_irq_root_dev = dev;
>         irq_root_filter = filter;
>         irq_root_arg = arg;
>         irq_root_ipicount = ipicount;
> @@ -1211,132 +1192,6 @@ dosoftints(void)
>
>  #ifdef SMP
>  /*
> - *  Lookup IPI source.
> - */
> -static struct intr_irqsrc *
> -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(struct intr_irqsrc *isrc, struct trapframe *tf)
> -{
> -       void *arg;
> -
> -       KASSERT(isrc != NULL, ("%s: no source", __func__));
> -
> -       isrc_increment_ipi_count(isrc, PCPU_GET(cpuid));
> -
> -       /*
> -        * Supply ipi filter with trapframe argument
> -        * if none is registered.
> -        */
> -       arg = isrc->isrc_arg != NULL ? isrc->isrc_arg : tf;
> -       isrc->isrc_ipifilter(arg);
> -}
> -
> -/*
> - *  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(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(irq_root_dev, isrc, &is_percpu);
> -
> -       debugf("ipi %u mapped to %u on %s - error %d\n", ipi, ipi_next_num,
> -           device_get_nameunit(irq_root_dev), error);
> -
> -       if (error == 0) {
> -               isrc->isrc_dev = 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_setup_ipi_counters(isrc, name);
> -
> -       if (isrc->isrc_dev != NULL) {
> -               mtx_lock(&isrc_table_lock);
> -               PIC_ENABLE_INTR(isrc->isrc_dev, isrc);
> -               PIC_ENABLE_SOURCE(isrc->isrc_dev, isrc);
> -               mtx_unlock(&isrc_table_lock);
> -       }
> -       return (0);
> -}
> -
> -/*
> - *  Send IPI thru interrupt controller.
> - */
> -void
> -pic_ipi_send(cpuset_t cpus, u_int ipi)
> -{
> -       struct intr_irqsrc *isrc;
> -
> -       isrc = intr_ipi_lookup(ipi);
> -
> -       KASSERT(irq_root_dev != NULL, ("%s: no root attached", __func__));
> -       PIC_IPI_SEND(irq_root_dev, isrc, cpus);
> -}
> -
> -/*
>   *  Init interrupt controller on another CPU.
>   */
>  void
> @@ -1346,10 +1201,10 @@ intr_pic_init_secondary(void)
>         /*
>          * QQQ: Only root PIC is aware of other CPUs ???
>          */
> -       KASSERT(irq_root_dev != NULL, ("%s: no root attached", __func__));
> +       KASSERT(intr_irq_root_dev != NULL, ("%s: no root attached", __func__));
>
>         //mtx_lock(&isrc_table_lock);
> -       PIC_INIT_SECONDARY(irq_root_dev);
> +       PIC_INIT_SECONDARY(intr_irq_root_dev);
>         //mtx_unlock(&isrc_table_lock);
>  }
>  #endif
> @@ -1360,25 +1215,6 @@ DB_SHOW_COMMAND(irqs, db_show_irqs)
>         u_int i, irqsum;
>         struct intr_irqsrc *isrc;
>
> -#ifdef SMP
> -       for (i = 0; i <= mp_maxid; i++) {
> -               struct pcpu *pc;
> -               u_int ipi, ipisum;
> -
> -               pc = pcpu_find(i);
> -               if (pc != NULL) {
> -                       for (ipisum = 0, ipi = 0; ipi < INTR_IPI_COUNT; ipi++) {
> -                               isrc = intr_ipi_lookup(ipi);
> -                               if (isrc->isrc_count != NULL)
> -                                       ipisum += isrc->isrc_count[i];
> -                       }
> -                       printf ("cpu%u: total %u ipis %u\n", i,
> -                           pc->pc_cnt.v_intr, ipisum);
> -               }
> -       }
> -       db_printf("\n");
> -#endif
> -
>         for (irqsum = 0, i = 0; i < NIRQ; i++) {
>                 isrc = irq_sources[i];
>                 if (isrc == NULL)
>
> Modified: head/sys/sys/intr.h
> ==============================================================================
> --- head/sys/sys/intr.h Sat Feb 27 03:38:01 2016        (r296137)
> +++ head/sys/sys/intr.h Sat Feb 27 12:03:07 2016        (r296138)
> @@ -39,6 +39,8 @@
>  #ifndef _SYS_INTR_H_
>  #define _SYS_INTR_H_
>
> +#include <sys/systm.h>
> +
>  #ifdef notyet
>  #define        INTR_SOLO       INTR_MD1
>  typedef int intr_irq_filter_t(void *arg, struct trapframe *tf);
> @@ -101,6 +103,8 @@ u_int intr_namespace_map_irq(device_t de
>  u_int intr_fdt_map_irq(phandle_t, pcell_t *, u_int);
>  #endif
>
> +extern device_t intr_irq_root_dev;
> +
>  int intr_pic_register(device_t dev, intptr_t xref);
>  int intr_pic_unregister(device_t dev, intptr_t xref);
>  int intr_pic_claim_root(device_t dev, intptr_t xref, intr_irq_filter_t *filter,
> @@ -117,14 +121,19 @@ u_int intr_irq_next_cpu(u_int current_cp
>  #ifdef SMP
>  int intr_irq_bind(u_int, int);
>
> -void intr_ipi_dispatch(struct intr_irqsrc *isrc, struct trapframe *tf);
> -
> -#define AISHF_NOALLOC  0x0001
> +void intr_pic_init_secondary(void);
>
> -int intr_ipi_set_handler(u_int ipi, const char *name, intr_ipi_filter_t *filter,
> -    void *arg, u_int flags);
> +/* Virtualization for interrupt source IPI counter increment. */
> +static inline void
> +intr_ipi_increment_count(u_long *counter, u_int cpu)
> +{
> +
> +       KASSERT(cpu < MAXCPU, ("%s: too big cpu %u", __func__, cpu));
> +       counter[cpu]++;
> +}
>
> -void intr_pic_init_secondary(void);
> +/* Virtualization for interrupt source IPI counters setup. */
> +u_long * intr_ipi_setup_counters(const char *name);
>
>  #endif
>  #endif /* _SYS_INTR_H */
>


More information about the svn-src-all mailing list