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#pragma ident	"%Z%%M%	%I%	%E% SMI"
28
29#include <sys/asm_linkage.h>
30#include <sys/machparam.h>	/* To get SYSBASE and PAGESIZE */
31#include <sys/privregs.h>
32
33#if !defined(lint)
34
35	.seg	".text"
36	.align	4
37
38#define	PSR_PIL_BIT	0x8
39
40/*
41 * Macro to raise processor priority level.
42 * Avoid dropping processor priority if already at high level.
43 * Also avoid going below CPU->cpu_base_spl, which could've just been set by
44 * a higher-level interrupt thread that just blocked.
45 * XXX4U: bring splr inline
46 */
47#define	RAISE(level) \
48	b	splr; \
49	mov	((level) << PSR_PIL_BIT), %o0
50/*
51 * Macro to set the priority to a specified level.
52 * Avoid dropping the priority below CPU->cpu_base_spl.
53 * XXX4U: bring splx inline
54 */
55#define SETPRI(level) \
56	b	splx; \
57	mov	((level) << PSR_PIL_BIT), %o0
58
59#endif	/* lint */
60
61	/*
62	 * Berkley 4.3 introduced symbolically named interrupt levels
63	 * as a way deal with priority in a machine independent fashion.
64	 * Numbered priorities are machine specific, and should be
65	 * discouraged where possible.
66	 *
67	 * Note, for the machine specific priorities there are
68	 * examples listed for devices that use a particular priority.
69	 * It should not be construed that all devices of that
70	 * type should be at that priority.  It is currently were
71	 * the current devices fit into the priority scheme based
72	 * upon time criticalness.
73	 *
74	 * The underlying assumption of these assignments is that
75	 * SPARC9 IPL 10 is the highest level from which a device
76	 * routine can call wakeup.  Devices that interrupt from higher
77	 * levels are restricted in what they can do.  If they need
78	 * kernels services they should schedule a routine at a lower
79	 * level (via software interrupt) to do the required
80	 * processing.
81	 *
82	 * Examples of this higher usage:
83	 *	Level	Usage
84	 *	15	Asynchronous memory exceptions
85	 *	14	Profiling clock (and PROM uart polling clock)
86	 *	13	Audio device
87	 *	12	Serial ports
88	 *	11	Floppy controller
89	 *
90	 * The serial ports request lower level processing on level 6.
91	 * Audio and floppy request lower level processing on level 4.
92	 *
93	 * Also, almost all splN routines (where N is a number or a
94	 * mnemonic) will do a RAISE(), on the assumption that they are
95	 * never used to lower our priority.
96	 * The exceptions are:
97	 *	spl8()		Because you can't be above 15 to begin with!
98	 *	splzs()		Because this is used at boot time to lower our
99	 *			priority, to allow the PROM to poll the uart.
100	 *	spl0()		Used to lower priority to 0.
101	 *	splsoftclock()	Used by hardclock to lower priority.
102	 */
103
104#if defined(lint)
105
106int splimp(void)	{ return (0); }
107int splnet(void)	{ return (0); }
108
109#ifdef	notdef
110int spl6(void)		{ return (0); }
111int spl5(void)		{ return (0); }
112#endif	notdef
113
114#else	/* lint */
115
116	/* locks out all interrupts, including memory errors */
117	ENTRY(spl8)
118	SETPRI(15)
119	SET_SIZE(spl8)
120
121	/* just below the level that profiling runs */
122	ALTENTRY(splaudio)
123	ENTRY(spl7)
124	RAISE(13)
125	SET_SIZE(spl7)
126	SET_SIZE(splaudio)
127
128	/* sun specific - highest priority onboard serial i/o zs ports */
129	ALTENTRY(splzs)
130	SETPRI(12)	/* Can't be a RAISE, as it's used to lower us */
131	SET_SIZE(splzs)
132
133	/*
134	 * should lock out clocks and all interrupts,
135	 * as you can see, there are exceptions
136	 */
137	ALTENTRY(splhigh)
138	ALTENTRY(splhi)
139
140	/* the standard clock interrupt priority */
141	ALTENTRY(splclock)
142
143	/* highest priority for any tty handling */
144	ALTENTRY(spltty)
145
146	/* highest priority required for protection of buffered io system */
147	ALTENTRY(splbio)
148
149	/* machine specific */
150	ENTRY2(spl6,spl5)
151	RAISE(10)
152	SET_SIZE(splhigh)
153	SET_SIZE(splhi)
154	SET_SIZE(splclock)
155	SET_SIZE(spltty)
156	SET_SIZE(splbio)
157	SET_SIZE(spl5)
158	SET_SIZE(spl6)
159
160	/*
161	 * machine specific
162	 * for sun, some frame buffers must be at this priority
163	 */
164	ENTRY(spl4)
165	RAISE(8)
166	SET_SIZE(spl4)
167
168	/* highest level that any network device will use */
169	ALTENTRY(splimp)
170
171	/*
172	 * machine specific
173	 * for sun, devices with limited buffering: tapes, ethernet
174	 */
175	ENTRY(spl3)
176	RAISE(6)
177	SET_SIZE(splimp)
178	SET_SIZE(spl3)
179
180	/*
181	 * machine specific - not as time critical as above
182	 * for sun, disks
183	 */
184	ENTRY(spl2)
185	RAISE(4)
186	SET_SIZE(spl2)
187
188	ENTRY(spl1)
189	RAISE(2)
190	SET_SIZE(spl1)
191
192	/* highest level that any protocol handler will run */
193	ENTRY(splnet)
194	RAISE(1)
195	SET_SIZE(splnet)
196
197	/* softcall priority */
198	/* used by hardclock to LOWER priority */
199	ENTRY(splsoftclock)
200	SETPRI(1)
201	SET_SIZE(splsoftclock)
202
203	/* allow all interrupts */
204	ENTRY(spl0)
205	SETPRI(0)
206	SET_SIZE(spl0)
207
208#endif	/* lint */
209
210/*
211 * splx - set PIL back to that indicated by the old %PSR passed as an argument,
212 * or to the CPU's base priority, whichever is higher.
213 * sys_rtt (in locore.s) relies on this not to use %g1 or %g2.
214 */
215
216#if defined(lint)
217
218/* ARGSUSED */
219void
220splx(int level)
221{
222}
223
224#else	/* lint */
225
226	ENTRY(splx)
227	rdpr	%pil, %o1	! get current pil
228	wrpr	%o0, %pil
229	retl
230	mov	%o1, %o0
231	SET_SIZE(splx)
232
233#endif	/* level */
234
235/*
236 * splr()
237 *
238 * splr is like splx but will only raise the priority and never drop it
239 * Be careful not to set priority lower than CPU->cpu_base_pri,
240 * even though it seems we're raising the priority, it could be set higher
241 * at any time by an interrupt routine, so we must block interrupts and
242 * look at CPU->cpu_base_pri.
243 *
244 */
245
246#if defined(lint)
247#ifdef	notdef
248
249/* ARGSUSED */
250int
251splr(int level)
252{ return (0); }
253
254#endif	notdef
255#else	/* lint */
256
257/*
258 * splr(psr_pri_field)
259 * splr is like splx but will only raise the priority and never drop it
260 */
261
262	ENTRY(splr)
263	rdpr	%pil, %o1	! get current pil
264	cmp	%o0, %o1
265	ble	1f
266	nop
267	wrpr	%o0, %pil
2681:	retl
269	mov	%o1, %o0	! return the old pil
270	SET_SIZE(splr)
271
272#endif	/* lint */
273
274/*
275 * get_ticks()
276 */
277#if defined(lint)
278
279/* ARGSUSED */
280uint64_t
281get_ticks(void)
282{ return (0); }
283
284#else	/* lint */
285
286	ENTRY(get_ticks)
287	rdpr	%tick, %o0
288	sllx	%o0, 1, %o0
289	retl
290	srlx	%o0, 1, %o0		! shake off npt bit
291	SET_SIZE(get_ticks)
292
293#endif	/* lint */
294