xref: /illumos-gate/usr/src/uts/common/sys/cyclic_impl.h (revision eb0cc229f19c437a6b538d3ac0d0443268290b7e)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #ifndef _SYS_CYCLIC_IMPL_H
28 #define	_SYS_CYCLIC_IMPL_H
29 
30 #pragma ident	"%Z%%M%	%I%	%E% SMI"
31 
32 #ifdef	__cplusplus
33 extern "C" {
34 #endif
35 
36 #include <sys/cyclic.h>
37 
38 /*
39  *  Cyclic Subsystem Backend-supplied Interfaces
40  *  --------------------------------------------
41  *
42  *  0  Background
43  *
44  *    The design, implementation and interfaces of the cyclic subsystem are
45  *    covered in detail in block comments in the implementation.  This
46  *    comment covers the interface from the cyclic subsystem into the cyclic
47  *    backend.  The backend is specified by a structure of function pointers
48  *    defined below.
49  *
50  *  1  Overview
51  *
52  *      cyb_configure()      <-- Configures the backend on the specified CPU
53  *      cyb_unconfigure()    <-- Unconfigures the backend
54  *      cyb_enable()         <-- Enables the CY_HIGH_LEVEL interrupt source
55  *      cyb_disable()        <-- Disables the CY_HIGH_LEVEL interrupt source
56  *      cyb_reprogram()      <-- Reprograms the CY_HIGH_LEVEL interrupt source
57  *      cyb_softint()        <-- Generates a soft interrupt
58  *      cyb_set_level()      <-- Sets the programmable interrupt level
59  *      cyb_restore_level()  <-- Restores the programmable interrupt level
60  *      cyb_xcall()          <-- Cross calls to the specified CPU
61  *      cyb_suspend()        <-- Suspends the backend
62  *      cyb_resume()         <-- Resumes the backend
63  *
64  *  2  cyb_arg_t cyb_configure(cpu_t *)
65  *
66  *  2.1  Overview
67  *
68  *    cyb_configure() should configure the specified CPU for cyclic operation.
69  *
70  *  2.2  Arguments and notes
71  *
72  *    cyb_configure() should initialize any backend-specific per-CPU
73  *    structures for the specified CPU.  cyb_configure() will be called for
74  *    each CPU (including the boot CPU) during boot.  If the platform
75  *    supports dynamic reconfiguration, cyb_configure() will be called for
76  *    new CPUs as they are configured into the system.
77  *
78  *  2.3  Return value
79  *
80  *    cyb_configure() is expected to return a cookie (a cyb_arg_t, which is
81  *    of type void *) which will be used as the first argument for all future
82  *    cyclic calls into the backend on the specified CPU.
83  *
84  *  2.4  Caller's context
85  *
86  *    cpu_lock will be held.  The caller's CPU is unspecified, and may or
87  *    may not be the CPU specified to cyb_configure().
88  *
89  *  3  void cyb_unconfigure(cyb_arg_t arg)
90  *
91  *  3.1  Overview
92  *
93  *    cyb_unconfigure() should unconfigure the specified backend.
94  *
95  *  3.2  Arguments and notes
96  *
97  *    The only argument to cyb_unconfigure() is a cookie as returned from
98  *    cyb_configure().
99  *
100  *    cyb_unconfigure() should free any backend-specific per-CPU structures
101  *    for the specified backend.  cyb_unconfigure() will _only_ be called on
102  *    platforms which support dynamic reconfiguration.  If the platform does
103  *    not support dynamic reconfiguration, cyb_unconfigure() may panic.
104  *
105  *    After cyb_unconfigure() returns, the backend must not call cyclic_fire()
106  *    on the corresponding CPU; doing so will result in a bad trap.
107  *
108  *  3.3  Return value
109  *
110  *    None.
111  *
112  *  3.4  Caller's context
113  *
114  *    cpu_lock will be held.  The caller's CPU is unspecified, and may or
115  *    may not be the CPU specified to cyb_unconfigure().  The specified
116  *    CPU is guaranteed to exist at the time cyb_unconfigure() is called.
117  *    The cyclic subsystem is guaranteed to be suspended when cyb_unconfigure()
118  *    is called, and interrupts are guaranteed to be disabled.
119  *
120  *  4  void cyb_enable(cyb_arg_t arg)
121  *
122  *  4.1  Overview
123  *
124  *    cyb_enable() should enable the CY_HIGH_LEVEL interrupt source on
125  *    the specified backend.
126  *
127  *  4.2  Arguments and notes
128  *
129  *    The only argument to cyb_enable() is a backend cookie as returned from
130  *    cyb_configure().
131  *
132  *    cyb_enable() will only be called if a) the specified backend has never
133  *    been enabled or b) the specified backend has been explicitly disabled with
134  *    cyb_disable().  In either case, cyb_enable() will only be called if
135  *    the cyclic subsystem wishes to add a cyclic to the CPU corresponding
136  *    to the specified backend.  cyb_enable() will be called before
137  *    cyb_reprogram() for a given backend.
138  *
139  *    cyclic_fire() should not be called on a CPU which has not had its backend
140  *    explicitly cyb_enable()'d, but to do so does not constitute fatal error.
141  *
142  *  4.3  Return value
143  *
144  *    None.
145  *
146  *  4.4  Caller's context
147  *
148  *    cyb_enable() will only be called from CY_HIGH_LEVEL context on the CPU
149  *    corresponding to the specified backend.
150  *
151  *  5  void cyb_disable(cyb_arg_t arg)
152  *
153  *  5.1  Overview
154  *
155  *    cyb_disable() should disable the CY_HIGH_LEVEL interrupt source on
156  *    the specified backend.
157  *
158  *  5.2  Arguments and notes
159  *
160  *    The only argument to cyb_disable() is a backend cookie as returned from
161  *    cyb_configure().
162  *
163  *    cyb_disable() will only be called on backends which have been previously
164  *    been cyb_enable()'d.  cyb_disable() will be called when all cyclics have
165  *    been juggled away or removed from a cyb_enable()'d CPU.
166  *
167  *    cyclic_fire() should not be called on a CPU which has had its backend
168  *    explicitly cyb_disable()'d, but to do so does not constitute fatal
169  *    error.  cyb_disable() is thus not required to check for a pending
170  *    CY_HIGH_LEVEL interrupt.
171  *
172  *  5.3  Return value
173  *
174  *    None.
175  *
176  *  5.4  Caller's context
177  *
178  *    cyb_disable() will only be called from CY_HIGH_LEVEL context on the CPU
179  *    corresponding to the specified backend.
180  *
181  *  6  void cyb_reprogram(cyb_arg_t arg, hrtime_t time)
182  *
183  *  6.1  Overview
184  *
185  *    cyb_reprogram() should reprogram the CY_HIGH_LEVEL interrupt source
186  *    to fire at the absolute time specified.
187  *
188  *  6.2  Arguments and notes
189  *
190  *    The first argument to cyb_reprogram() is a backend cookie as returned from
191  *    cyb_configure().
192  *
193  *    The second argument is an absolute time at which the CY_HIGH_LEVEL
194  *    interrupt should fire.  The specified time _may_ be in the past (albeit
195  *    the very recent past).  If this is the case, the backend should generate
196  *    a CY_HIGH_LEVEL interrupt as soon as possible.
197  *
198  *    The platform should not assume that cyb_reprogram() will be called with
199  *    monotonically increasing values.
200  *
201  *    If the platform does not allow for interrupts at arbitrary times in the
202  *    future, cyb_reprogram() may do nothing -- as long as cyclic_fire() is
203  *    called periodically at CY_HIGH_LEVEL.  While this is clearly suboptimal
204  *    (cyclic granularity will be bounded by the length of the period between
205  *    cyclic_fire()'s), it allows the cyclic subsystem to be implemented on
206  *    inferior hardware.
207  *
208  *  6.3  Return value
209  *
210  *     None.
211  *
212  *  6.4  Caller's context
213  *
214  *    cyb_reprogram() will only be called from CY_HIGH_LEVEL context on the CPU
215  *    corresponding to the specified backend.
216  *
217  *  7  void cyb_softint(cyb_arg_t arg, cyc_level_t level)
218  *
219  *  7.1  Overview
220  *
221  *    cyb_softint() should generate a software interrupt on the specified
222  *    backend at the specified level.
223  *
224  *  7.2  Arguments and notes
225  *
226  *    The first argument to cyb_softint() is a backend cookie as returned from
227  *    cyb_configure().  The second argument is the interrupt level at which
228  *    the software interrupt should be generated; it will be either
229  *    CY_LOCK_LEVEL or CY_LOW_LEVEL.
230  *
231  *    The software interrupt _must_ be generated on the CPU corresponding
232  *    to the specified backend; platforms are _required_ to have a per-CPU
233  *    notion of a software interrupt.
234  *
235  *    Unless a software interrupt is already pending at the specified level,
236  *    the software interrupt _must_ be generated.  Once cyclic_softint()
237  *    has been called at a given level, the software interrupt at that level
238  *    should no longer be considered pending; an intervening CY_HIGH_LEVEL
239  *    interrupt and subsequent cyb_softint() must generate another software
240  *    interrupt.
241  *
242  *  7.3  Return value
243  *
244  *    None.
245  *
246  *  7.4  Caller's context
247  *
248  *    cyb_softint() will only be called at a level higher than the one
249  *    specified:  if CY_LOCK_LEVEL is specified, the caller will be at
250  *    CY_HIGH_LEVEL; if CY_LOW_LEVEL is specified, the caller will be at
251  *    either CY_HIGH_LEVEL or CY_LOCK_LEVEL.  cyb_softint() will only be
252  *    called on the CPU corresponding to the specified backend.
253  *
254  *  8  cyb_set_level(cyb_arg_t arg, cyc_level_t level)
255  *
256  *  8.1  Overview
257  *
258  *    cyb_set_level() should set the programmable interrupt level to the
259  *    level specified.
260  *
261  *  8.2  Arguments and notes
262  *
263  *    The first argument to cyb_set_level() is a backend cookie as returned
264  *    from cyb_configure().  The second argument is the level to which
265  *    the programmable interrupt level should be set; it will be one of
266  *    CY_HIGH_LEVEL, CY_LOCK_LEVEL or CY_LOW_LEVEL.
267  *
268  *    After cyb_set_level() returns, the CPU associated with the specified
269  *    backend should accept no interrupt at a level greater than or equal to
270  *    the specified level.  This will generally be a wrapper around splx().
271  *
272  *    The cyclic subsystem will never call cyb_set_level() twice consecutively
273  *    on the same backend; there will always be an intervening
274  *    cyb_restore_level();
275  *
276  *  8.3  Return value
277  *
278  *    cyb_set_level() should return a cookie to be passed back to
279  *    cyb_restore_level().  On most implementations, this cookie will be
280  *    the spl at the time of cyb_set_level().
281  *
282  *  8.4  Caller's context
283  *
284  *    cyb_set_level() is unique in that it is the only backend-provided
285  *    interface which may be called in cross call context (see cyb_xcall(),
286  *    below).  cyb_set_level() may also be called from any of the cyclic
287  *
288  *  9  cyb_restore_level(cyb_arg_t arg, cyc_cookie_t cookie)
289  *
290  *  9.1  Overview
291  *
292  *    cyb_restore_level() should restore the programmable interrupt level
293  *    based upon the specified cookie.
294  *
295  *  9.2  Arguments and notes
296  *
297  *    The first argument to cyb_restore_level() is a backend cookie as returned
298  *    from cyb_configure().  The second argument is a cookie as returned from
299  *    cyb_set_level().
300  *
301  *    cyb_restore_level() should restore the programmable interrupt level
302  *    to its value when cyb_set_level() was called; the cookie is used
303  *    to provide a hint to the backend.  cyb_restore_level() will not be
304  *    called without a proceeding call to cyb_set_level(), and
305  *    cyb_restore_level() will never be called twice consecutively on the
306  *    same backend.
307  *
308  *  9.3  Return value
309  *
310  *    None.
311  *
312  *  9.4  Caller's context
313  *
314  *    The constraints outlined in 5.9.2 imply that cyb_restore_level() can
315  *    only be called from CY_HIGH_LEVEL, CY_LOCK_LEVEL or CY_LOW_LEVEL context.
316  *    cyb_restore_level() is always called on the CPU associated with the
317  *    specified backend.
318  *
319  *  10  cyb_xcall(cyb_arg_t arg, cpu_t *, void(*func)(void *), void *farg)
320  *
321  *  10.1  Overview
322  *
323  *    cyb_xcall() should execute the specified function on the specified CPU.
324  *
325  *  10.2  Arguments and notes
326  *
327  *    The first argument to cyb_restore_level() is a backend cookie as returned
328  *    from cyb_configure().  The second argument is a CPU on which the third
329  *    argument, a function pointer, should be executed.  The fourth argument,
330  *    a void *, should be passed as the argument to the specified function.
331  *
332  *    cyb_xcall() must provide exactly-once semantics.  If the specified
333  *    function is called more than once, or not at all, the cyclic subsystem
334  *    will become internally inconsistent.  The specified function must be
335  *    be executed on the specified CPU, but may be executed in any context
336  *    (any interrupt context or kernel context).
337  *
338  *    cyb_xcall() cannot block.  Any resources which cyb_xcall() needs to
339  *    acquire must thus be protected by synchronization primitives which
340  *    never require the caller to block.
341  *
342  *  10.3  Return value
343  *
344  *    None.
345  *
346  *  10.4  Caller's context
347  *
348  *    cpu_lock will be held and kernel preemption may be disabled.  The caller
349  *    may be unable to block, giving rise to the constraint outlined in
350  *    10.2, above.
351  *
352  *  11  cyb_suspend(cyb_arg_t arg)
353  *
354  *  11.1  Overview
355  *
356  *    cyb_suspend() should suspend the specified backend.
357  *
358  *  11.2  Arguments and notes
359  *
360  *    The only argument to cyb_suspend() is a backend cookie as returned from
361  *    cyb_configure().
362  *
363  *    cyb_suspend() will never be called on enabled backends.  The backend
364  *    should assume that the machine may be subsequently powered off; any
365  *    volatile hardware state should be preserved and restored in cyb_resume().
366  *    However, the backend should not _assume_ that the machine will be
367  *    powered off; cyb_suspend() may also be called as part of dynamic
368  *    reconfiguration.
369  *
370  *    cyb_suspend() will be called on the corresponding backend of each
371  *    CPU in the system in succession, regardless of CPU state (P_ONLINE,
372  *    P_OFFLINE, P_NOINTR).  The cyclic subsystem will not suspend only a
373  *    fraction of the CPUs.
374  *
375  *  11.3  Return value
376  *
377  *    None.
378  *
379  *  11.4  Caller's context
380  *
381  *    cyb_suspend() will be called in cross call context on the CPU associated
382  *    with the specified backend.
383  *
384  *  12  cyb_resume(cyb_arg_t arg)
385  *
386  *  12.1  Overview
387  *
388  *    cyb_resume() should resume the specified backend.
389  *
390  *  12.2  Arguments and notes
391  *
392  *    The only argument to cyb_resume() is a backend cookie as returned from
393  *    cyb_resume().
394  *
395  *    Calls to cyb_resume() will always have been proceeded by corresponding
396  *    calls to cyb_suspend().  The machine may have been powered off between
397  *    cyb_suspend() and the call to cyb_resume().  cyb_resume() may decide
398  *    to restore hardware to its state at the time cyb_suspend() was called.
399  *
400  *    The cyclic subsystem will make no calls into the backend between
401  *    cyb_suspend() and cyb_resume().
402  *
403  *  12.3  Return value
404  *
405  *    None.
406  *
407  *  12.4  Caller's context
408  *
409  *    cyb_resume() will be called in cross call context on the CPU associated
410  *    with the specified backend.
411  */
412 typedef struct cyc_backend {
413 	cyb_arg_t (*cyb_configure)(cpu_t *);
414 	void (*cyb_unconfigure)(cyb_arg_t);
415 	void (*cyb_enable)(cyb_arg_t);
416 	void (*cyb_disable)(cyb_arg_t);
417 	void (*cyb_reprogram)(cyb_arg_t, hrtime_t);
418 	void (*cyb_softint)(cyb_arg_t, cyc_level_t);
419 	cyc_cookie_t (*cyb_set_level)(cyb_arg_t, cyc_level_t);
420 	void (*cyb_restore_level)(cyb_arg_t, cyc_cookie_t);
421 	void (*cyb_xcall)(cyb_arg_t, cpu_t *, cyc_func_t, void *);
422 	void (*cyb_suspend)(cyb_arg_t);
423 	void (*cyb_resume)(cyb_arg_t);
424 	cyb_arg_t cyb_arg;
425 } cyc_backend_t;
426 
427 extern void cyclic_init(cyc_backend_t *be, hrtime_t resolution);
428 extern void cyclic_mp_init();
429 
430 #ifdef DEBUG
431 #define	CYCLIC_TRACE
432 #endif
433 
434 typedef enum {
435 	CYS_ONLINE,
436 	CYS_OFFLINE,
437 	CYS_EXPANDING,
438 	CYS_REMOVING,
439 	CYS_SUSPENDED
440 } cyc_state_t;
441 
442 #define	CYF_FREE		0x0001
443 #define	CYF_CPU_BOUND		0x0002
444 #define	CYF_PART_BOUND		0x0004
445 
446 typedef struct cyclic {
447 	hrtime_t cy_expire;
448 	hrtime_t cy_interval;
449 	void (*cy_handler)(void *);
450 	void *cy_arg;
451 	uint32_t cy_pend;
452 	uint16_t cy_flags;
453 	cyc_level_t cy_level;
454 } cyclic_t;
455 
456 typedef struct cyc_pcbuffer {
457 	cyc_index_t *cypc_buf;
458 	int cypc_prodndx;
459 	int cypc_consndx;
460 	int cypc_sizemask;
461 } cyc_pcbuffer_t;
462 
463 typedef struct cyc_softbuf {
464 	uchar_t cys_hard;		/* Can only be zero or one */
465 	uchar_t cys_soft;		/* Can only be zero or one */
466 	cyc_pcbuffer_t cys_buf[2];
467 } cyc_softbuf_t;
468 
469 #define	CY_NTRACEREC		512
470 
471 typedef struct cyc_tracerec {
472 	hrtime_t cyt_tstamp;
473 	char *cyt_why;
474 	uint64_t cyt_arg0;
475 	uint64_t cyt_arg1;
476 } cyc_tracerec_t;
477 
478 typedef struct cyc_tracebuf {
479 	int cyt_ndx;
480 	cyc_tracerec_t cyt_buf[CY_NTRACEREC];
481 } cyc_tracebuf_t;
482 
483 #define	CY_NCOVERAGE	127
484 
485 typedef struct cyc_coverage {
486 	char *cyv_why;
487 	int cyv_passive_count;
488 	int cyv_count[CY_LEVELS];
489 	uint64_t cyv_arg0;
490 	uint64_t cyv_arg1;
491 } cyc_coverage_t;
492 
493 typedef struct cyc_cpu {
494 	cpu_t *cyp_cpu;
495 	cyc_index_t *cyp_heap;
496 	cyclic_t *cyp_cyclics;
497 	cyc_index_t cyp_nelems;
498 	cyc_index_t cyp_size;
499 	cyc_state_t cyp_state;
500 	cyc_softbuf_t cyp_softbuf[CY_SOFT_LEVELS];
501 	cyc_backend_t *cyp_backend;
502 	ksema_t cyp_modify_wait;
503 	uint32_t cyp_modify_levels;
504 	uint32_t cyp_rpend;
505 #ifdef CYCLIC_TRACE
506 	cyc_tracebuf_t cyp_trace[CY_LEVELS];
507 #endif
508 } cyc_cpu_t;
509 
510 typedef struct cyc_omni_cpu {
511 	cyc_cpu_t *cyo_cpu;
512 	cyc_index_t cyo_ndx;
513 	void *cyo_arg;
514 	struct cyc_omni_cpu *cyo_next;
515 } cyc_omni_cpu_t;
516 
517 typedef struct cyc_id {
518 	cyc_cpu_t *cyi_cpu;
519 	cyc_index_t cyi_ndx;
520 	struct cyc_id *cyi_prev;
521 	struct cyc_id *cyi_next;
522 	cyc_omni_handler_t cyi_omni_hdlr;
523 	cyc_omni_cpu_t *cyi_omni_list;
524 } cyc_id_t;
525 
526 typedef struct cyc_xcallarg {
527 	cyc_cpu_t *cyx_cpu;
528 	cyc_handler_t *cyx_hdlr;
529 	cyc_time_t *cyx_when;
530 	cyc_index_t cyx_ndx;
531 	cyc_index_t *cyx_heap;
532 	cyclic_t *cyx_cyclics;
533 	cyc_index_t cyx_size;
534 	uint16_t cyx_flags;
535 	int cyx_wait;
536 } cyc_xcallarg_t;
537 
538 #define	CY_DEFAULT_PERCPU	1
539 #define	CY_PASSIVE_LEVEL	-1
540 
541 #define	CY_WAIT			0
542 #define	CY_NOWAIT		1
543 
544 #define	CYC_HEAP_PARENT(ndx)		(((ndx) - 1) >> 1)
545 #define	CYC_HEAP_RIGHT(ndx)		(((ndx) + 1) << 1)
546 #define	CYC_HEAP_LEFT(ndx)		((((ndx) + 1) << 1) - 1)
547 
548 #ifdef	__cplusplus
549 }
550 #endif
551 
552 #endif /* _SYS_CYCLIC_IMPL_H */
553