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