Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src Support arbitrary softint IPLs in high priority xcall



details:   https://anonhg.NetBSD.org/src/rev/57023c815542
branches:  trunk
changeset: 829441:57023c815542
user:      ozaki-r <ozaki-r%NetBSD.org@localhost>
date:      Thu Feb 01 03:15:28 2018 +0000

description:
Support arbitrary softint IPLs in high priority xcall

The high priority xcall supported only a softint of IPL_SOFTSERIAL. It meant
that it didn't work for xcall callbacks depending on lower IPLs than
IPL_SOFTSERIAL.

The change makes xcall have multiple softints of IPLs and allow users to specify
arbitrary IPLs. Users can specify an IPL by XC_HIGHPRI_IPL passed to the 1st
argument of xc_broadcast or xc_unicast.

Note that xcall still serves requests one by one (i.e., doesn't run them
concurrently) even if requests have different IPLs.

Proposed on tech-kern@

diffstat:

 share/man/man9/xcall.9 |  16 +++++++-
 sys/kern/subr_xcall.c  |  92 ++++++++++++++++++++++++++++++++++++++++++-------
 sys/sys/xcall.h        |   7 ++-
 3 files changed, 97 insertions(+), 18 deletions(-)

diffs (264 lines):

diff -r 4c0c164ddba8 -r 57023c815542 share/man/man9/xcall.9
--- a/share/man/man9/xcall.9    Thu Feb 01 02:50:51 2018 +0000
+++ b/share/man/man9/xcall.9    Thu Feb 01 03:15:28 2018 +0000
@@ -1,4 +1,4 @@
-.\"     $NetBSD: xcall.9,v 1.11 2018/01/26 08:09:53 ozaki-r Exp $
+.\"     $NetBSD: xcall.9,v 1.12 2018/02/01 03:15:28 ozaki-r Exp $
 .\"
 .\" Copyright (c) 2010 The NetBSD Foundation, Inc.
 .\" All rights reserved.
@@ -27,7 +27,7 @@
 .\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 .\" POSSIBILITY OF SUCH DAMAGE.
 .\"
-.Dd January 26, 2018
+.Dd February 1, 2018
 .Dt XCALL 9
 .Os
 .Sh NAME
@@ -87,7 +87,6 @@
 .Dq "high priority"
 cross calls.
 The function to be executed runs on the remote CPU within a
-.Dv IPL_SOFTSERIAL
 software interrupt context, possibly interrupting other lower-priority
 code running on the CPU.
 .Sh NOTES
@@ -112,7 +111,18 @@
 .Fa flags
 should be
 .Dv XC_HIGHPRI
+or
+.Fo XC_HIGHPRI_IPL
+.Fa ipl
+.Fc
 for a "high priority" call, and 0 for a "low priority" call.
+.Dv XC_HIGHPRI
+uses an
+.Dv IPL_SOFTSERIAL
+software interrupt while
+.Fn XC_HIGHPRI_IPL
+uses a software interrupt with an IPL specified by
+.Fa ipl .
 .Fn xc_broadcast
 should not be called from interrupt context.
 .It Fn xc_unicast "flags" "func" "arg1" "arg2" "ci"
diff -r 4c0c164ddba8 -r 57023c815542 sys/kern/subr_xcall.c
--- a/sys/kern/subr_xcall.c     Thu Feb 01 02:50:51 2018 +0000
+++ b/sys/kern/subr_xcall.c     Thu Feb 01 03:15:28 2018 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: subr_xcall.c,v 1.20 2017/06/21 07:39:04 martin Exp $   */
+/*     $NetBSD: subr_xcall.c,v 1.21 2018/02/01 03:15:29 ozaki-r Exp $  */
 
 /*-
  * Copyright (c) 2007-2010 The NetBSD Foundation, Inc.
@@ -74,7 +74,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: subr_xcall.c,v 1.20 2017/06/21 07:39:04 martin Exp $");
+__KERNEL_RCSID(0, "$NetBSD: subr_xcall.c,v 1.21 2018/02/01 03:15:29 ozaki-r Exp $");
 
 #include <sys/types.h>
 #include <sys/param.h>
@@ -98,6 +98,7 @@
        void *          xc_arg2;
        uint64_t        xc_headp;
        uint64_t        xc_donep;
+       unsigned int    xc_ipl;
 } xc_state_t;
 
 /* Bit indicating high (1) or low (0) priority. */
@@ -108,7 +109,7 @@
 
 /* High priority xcall structures. */
 static xc_state_t      xc_high_pri     __cacheline_aligned;
-static void *          xc_sih          __cacheline_aligned;
+static void *          xc_sihs[4]      __cacheline_aligned;
 
 /* Event counters. */
 static struct evcnt    xc_unicast_ev   __cacheline_aligned;
@@ -117,9 +118,24 @@
 static void            xc_init(void);
 static void            xc_thread(void *);
 
-static inline uint64_t xc_highpri(xcfunc_t, void *, void *, struct cpu_info *);
+static inline uint64_t xc_highpri(xcfunc_t, void *, void *, struct cpu_info *,
+                           unsigned int);
 static inline uint64_t xc_lowpri(xcfunc_t, void *, void *, struct cpu_info *);
 
+/* The internal form of IPL */
+#define XC_IPL_MASK            0xff00
+/*
+ * Assign 0 to XC_IPL_SOFTSERIAL to treat IPL_SOFTSERIAL as the default value
+ * (just XC_HIGHPRI).
+ */
+#define XC_IPL_SOFTSERIAL      0
+#define XC_IPL_SOFTBIO         1
+#define XC_IPL_SOFTCLOCK       2
+#define XC_IPL_SOFTNET         3
+#define XC_IPL_MAX             XC_IPL_SOFTNET
+
+CTASSERT(XC_IPL_MAX <= __arraycount(xc_sihs));
+
 /*
  * xc_init:
  *
@@ -137,9 +153,19 @@
        memset(xchi, 0, sizeof(xc_state_t));
        mutex_init(&xchi->xc_lock, MUTEX_DEFAULT, IPL_SOFTSERIAL);
        cv_init(&xchi->xc_busy, "xchicv");
-       xc_sih = softint_establish(SOFTINT_SERIAL | SOFTINT_MPSAFE,
-           xc__highpri_intr, NULL);
-       KASSERT(xc_sih != NULL);
+
+#define SETUP_SOFTINT(xipl, sipl) do {                                 \
+               xc_sihs[(xipl)] = softint_establish( (sipl) | SOFTINT_MPSAFE,\
+                   xc__highpri_intr, NULL);                            \
+               KASSERT(xc_sihs[(xipl)] != NULL);                       \
+       } while (0)
+
+       SETUP_SOFTINT(XC_IPL_SOFTSERIAL, SOFTINT_SERIAL);
+       SETUP_SOFTINT(XC_IPL_SOFTBIO, SOFTINT_BIO);
+       SETUP_SOFTINT(XC_IPL_SOFTCLOCK, SOFTINT_CLOCK);
+       SETUP_SOFTINT(XC_IPL_SOFTNET, SOFTINT_NET);
+
+#undef SETUP_SOFTINT
 
        evcnt_attach_dynamic(&xc_unicast_ev, EVCNT_TYPE_MISC, NULL,
           "crosscall", "unicast");
@@ -148,6 +174,38 @@
 }
 
 /*
+ * Encode an IPL to a form that can be embedded into flags of xc_broadcast
+ * or xc_unicast.
+ */
+unsigned int
+xc_encode_ipl(int ipl)
+{
+
+       switch (ipl) {
+       case IPL_SOFTSERIAL:
+               return __SHIFTIN(XC_IPL_SOFTSERIAL, XC_IPL_MASK);
+       case IPL_SOFTBIO:
+               return __SHIFTIN(XC_IPL_SOFTBIO, XC_IPL_MASK);
+       case IPL_SOFTCLOCK:
+               return __SHIFTIN(XC_IPL_SOFTCLOCK, XC_IPL_MASK);
+       case IPL_SOFTNET:
+               return __SHIFTIN(XC_IPL_SOFTNET, XC_IPL_MASK);
+       }
+
+       panic("Invalid IPL: %d", ipl);
+}
+
+/*
+ * Extract an XC_IPL from flags of xc_broadcast or xc_unicast.
+ */
+static inline unsigned int
+xc_extract_ipl(unsigned int flags)
+{
+
+       return __SHIFTOUT(flags, XC_IPL_MASK);
+}
+
+/*
  * xc_init_cpu:
  *
  *     Initialize the cross-call subsystem.  Called once for each CPU
@@ -176,13 +234,14 @@
  *     Trigger a call on all CPUs in the system.
  */
 uint64_t
-xc_broadcast(u_int flags, xcfunc_t func, void *arg1, void *arg2)
+xc_broadcast(unsigned int flags, xcfunc_t func, void *arg1, void *arg2)
 {
 
        KASSERT(!cpu_intr_p() && !cpu_softintr_p());
 
        if ((flags & XC_HIGHPRI) != 0) {
-               return xc_highpri(func, arg1, arg2, NULL);
+               int ipl = xc_extract_ipl(flags);
+               return xc_highpri(func, arg1, arg2, NULL, ipl);
        } else {
                return xc_lowpri(func, arg1, arg2, NULL);
        }
@@ -194,7 +253,7 @@
  *     Trigger a call on one CPU.
  */
 uint64_t
-xc_unicast(u_int flags, xcfunc_t func, void *arg1, void *arg2,
+xc_unicast(unsigned int flags, xcfunc_t func, void *arg1, void *arg2,
           struct cpu_info *ci)
 {
 
@@ -202,7 +261,8 @@
        KASSERT(!cpu_intr_p() && !cpu_softintr_p());
 
        if ((flags & XC_HIGHPRI) != 0) {
-               return xc_highpri(func, arg1, arg2, ci);
+               int ipl = xc_extract_ipl(flags);
+               return xc_highpri(func, arg1, arg2, ci, ipl);
        } else {
                return xc_lowpri(func, arg1, arg2, ci);
        }
@@ -329,8 +389,12 @@
 void
 xc_ipi_handler(void)
 {
+       xc_state_t *xc = & xc_high_pri;
+
+       KASSERT(xc->xc_ipl < __arraycount(xc_sihs));
+
        /* Executes xc__highpri_intr() via software interrupt. */
-       softint_schedule(xc_sih);
+       softint_schedule(xc_sihs[xc->xc_ipl]);
 }
 
 /*
@@ -376,7 +440,8 @@
  *     Trigger a high priority call on one or more CPUs.
  */
 static inline uint64_t
-xc_highpri(xcfunc_t func, void *arg1, void *arg2, struct cpu_info *ci)
+xc_highpri(xcfunc_t func, void *arg1, void *arg2, struct cpu_info *ci,
+    unsigned int ipl)
 {
        xc_state_t *xc = &xc_high_pri;
        uint64_t where;
@@ -389,6 +454,7 @@
        xc->xc_arg1 = arg1;
        xc->xc_arg2 = arg2;
        xc->xc_headp += (ci ? 1 : ncpu);
+       xc->xc_ipl = ipl;
        where = xc->xc_headp;
        mutex_exit(&xc->xc_lock);
 
diff -r 4c0c164ddba8 -r 57023c815542 sys/sys/xcall.h
--- a/sys/sys/xcall.h   Thu Feb 01 02:50:51 2018 +0000
+++ b/sys/sys/xcall.h   Thu Feb 01 03:15:28 2018 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: xcall.h,v 1.5 2013/02/19 09:04:53 martin Exp $ */
+/*     $NetBSD: xcall.h,v 1.6 2018/02/01 03:15:29 ozaki-r Exp $        */
 
 /*-
  * Copyright (c) 2007 The NetBSD Foundation, Inc.
@@ -33,7 +33,8 @@
 #define        _SYS_XCALL_H_
 
 #ifdef _KERNEL
-#define        XC_HIGHPRI      0x01    /* high priority */
+#define XC_HIGHPRI             0x01    /* high priority */
+#define XC_HIGHPRI_IPL(ipl)    (XC_HIGHPRI | xc_encode_ipl(ipl))
 
 typedef void (*xcfunc_t)(void *, void *);
 
@@ -49,6 +50,8 @@
 uint64_t       xc_unicast(u_int, xcfunc_t, void *, void *, struct cpu_info *);
 void           xc_wait(uint64_t);
 
+unsigned int   xc_encode_ipl(int);
+
 #endif /* _KERNEL */
 
 #endif /* _SYS_XCALL_H_ */



Home | Main Index | Thread Index | Old Index