]>
Commit | Line | Data |
---|---|---|
1c79356b A |
1 | /* |
2 | * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. | |
3 | * | |
4 | * @APPLE_LICENSE_HEADER_START@ | |
5 | * | |
e5568f75 A |
6 | * The contents of this file constitute Original Code as defined in and |
7 | * are subject to the Apple Public Source License Version 1.1 (the | |
8 | * "License"). You may not use this file except in compliance with the | |
9 | * License. Please obtain a copy of the License at | |
10 | * http://www.apple.com/publicsource and read it before using this file. | |
1c79356b | 11 | * |
e5568f75 A |
12 | * This Original Code and all software distributed under the License are |
13 | * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER | |
1c79356b A |
14 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, |
15 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, | |
e5568f75 A |
16 | * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the |
17 | * License for the specific language governing rights and limitations | |
18 | * under the License. | |
1c79356b A |
19 | * |
20 | * @APPLE_LICENSE_HEADER_END@ | |
21 | */ | |
22 | /* | |
23 | * @OSF_COPYRIGHT@ | |
24 | */ | |
25 | /* | |
26 | * Mach Operating System | |
27 | * Copyright (c) 1991,1990 Carnegie Mellon University | |
28 | * All Rights Reserved. | |
29 | * | |
30 | * Permission to use, copy, modify and distribute this software and its | |
31 | * documentation is hereby granted, provided that both the copyright | |
32 | * notice and this permission notice appear in all copies of the | |
33 | * software, derivative works or modified versions, and any portions | |
34 | * thereof, and that both notices appear in supporting documentation. | |
35 | * | |
36 | * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" | |
37 | * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR | |
38 | * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. | |
39 | * | |
40 | * Carnegie Mellon requests users of this software to return to | |
41 | * | |
42 | * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU | |
43 | * School of Computer Science | |
44 | * Carnegie Mellon University | |
45 | * Pittsburgh PA 15213-3890 | |
46 | * | |
47 | * any improvements or extensions that they make and grant Carnegie Mellon | |
48 | * the rights to redistribute these changes. | |
49 | */ | |
50 | ||
51 | /* | |
52 | */ | |
53 | ||
54 | #ifndef _I386AT_MP_H_ | |
55 | #define _I386AT_MP_H_ | |
56 | ||
55e303ae | 57 | #if !defined(NCPUS) |
1c79356b | 58 | #include <cpus.h> |
55e303ae | 59 | #endif /* !defined(NCPUS) */ |
1c79356b A |
60 | |
61 | #if NCPUS > 1 | |
55e303ae A |
62 | |
63 | #ifndef DEBUG | |
64 | #include <debug.h> | |
65 | #endif | |
66 | #if DEBUG | |
67 | #define MP_DEBUG 1 | |
68 | #endif | |
69 | ||
1c79356b | 70 | #include <i386/apic.h> |
55e303ae A |
71 | #include <i386/mp_events.h> |
72 | ||
73 | #define SPURIOUS_INTERRUPT 0xDD | |
74 | #define INTERPROCESS_INTERRUPT 0xDE | |
75 | #define APIC_ERROR_INTERRUPT 0xDF | |
76 | ||
77 | #define LAPIC_ID_MAX (LAPIC_ID_MASK) | |
78 | ||
79 | #ifndef ASSEMBLER | |
80 | extern void lapic_dump(void); | |
81 | extern void lapic_interrupt(int interrupt, void *state); | |
82 | extern int lapic_to_cpu[]; | |
83 | extern int cpu_to_lapic[]; | |
84 | extern void lapic_cpu_map(int lapic, int cpu_num); | |
85 | #endif /* ASSEMBLER */ | |
1c79356b | 86 | |
55e303ae A |
87 | #define CPU_NUMBER(r) \ |
88 | movl EXT(lapic_id),r; \ | |
89 | movl 0(r),r; \ | |
90 | shrl $(LAPIC_ID_SHIFT),r; \ | |
91 | andl $(LAPIC_ID_MASK),r; \ | |
92 | movl EXT(lapic_to_cpu)(,r,4),r | |
1c79356b A |
93 | |
94 | ||
95 | #define MP_IPL SPL6 /* software interrupt level */ | |
96 | ||
97 | /* word describing the reason for the interrupt, one per cpu */ | |
98 | ||
99 | #ifndef ASSEMBLER | |
100 | #include <kern/lock.h> | |
55e303ae A |
101 | extern int real_ncpus; /* real number of cpus */ |
102 | extern int wncpu; /* wanted number of cpus */ | |
1c79356b | 103 | decl_simple_lock_data(extern,kdb_lock) /* kdb lock */ |
55e303ae | 104 | decl_simple_lock_data(extern,mp_putc_lock) |
1c79356b A |
105 | |
106 | extern int kdb_cpu; /* current cpu running kdb */ | |
107 | extern int kdb_debug; | |
108 | extern int kdb_is_slave[]; | |
109 | extern int kdb_active[]; | |
55e303ae A |
110 | |
111 | extern volatile boolean_t mp_kdp_trap; | |
112 | extern void mp_trap_enter(); | |
113 | extern void mp_trap_exit(); | |
114 | ||
115 | /* | |
116 | * All cpu rendezvous: | |
117 | */ | |
118 | extern void mp_rendezvous(void (*setup_func)(void *), | |
119 | void (*action_func)(void *), | |
120 | void (*teardown_func)(void *), | |
121 | void *arg); | |
122 | ||
123 | #if MP_DEBUG | |
124 | typedef struct { | |
125 | uint64_t time; | |
126 | int cpu; | |
127 | mp_event_t event; | |
128 | } cpu_signal_event_t; | |
129 | ||
130 | #define LOG_NENTRIES 100 | |
131 | typedef struct { | |
132 | uint64_t count[MP_LAST]; | |
133 | int next_entry; | |
134 | cpu_signal_event_t entry[LOG_NENTRIES]; | |
135 | } cpu_signal_event_log_t; | |
136 | ||
137 | extern cpu_signal_event_log_t cpu_signal[NCPUS]; | |
138 | extern cpu_signal_event_log_t cpu_handle[NCPUS]; | |
139 | ||
140 | #define DBGLOG(log,_cpu,_event) { \ | |
141 | cpu_signal_event_log_t *logp = &log[cpu_number()]; \ | |
142 | int next = logp->next_entry; \ | |
143 | cpu_signal_event_t *eventp = &logp->entry[next]; \ | |
144 | boolean_t spl = ml_set_interrupts_enabled(FALSE); \ | |
145 | \ | |
146 | logp->count[_event]++; \ | |
147 | \ | |
148 | eventp->time = rdtsc64(); \ | |
149 | eventp->cpu = _cpu; \ | |
150 | eventp->event = _event; \ | |
151 | if (next == (LOG_NENTRIES - 1)) \ | |
152 | logp->next_entry = 0; \ | |
153 | else \ | |
154 | logp->next_entry++; \ | |
155 | \ | |
156 | (void) ml_set_interrupts_enabled(spl); \ | |
157 | } | |
158 | #else /* MP_DEBUG */ | |
159 | #define DBGLOG(log,_cpu,_event) | |
160 | #endif /* MP_DEBUG */ | |
161 | ||
1c79356b A |
162 | #endif /* ASSEMBLER */ |
163 | ||
164 | #define i_bit(bit, word) ((long)(*(word)) & ((long)1 << (bit))) | |
165 | ||
166 | ||
167 | /* | |
168 | * Device driver synchronization. | |
169 | * | |
170 | * at386_io_lock(op) and at386_io_unlock() are called | |
171 | * by device drivers when accessing H/W. The underlying | |
172 | * Processing is machine dependant. But the op argument | |
173 | * to the at386_io_lock is generic | |
174 | */ | |
175 | ||
176 | #define MP_DEV_OP_MAX 4 | |
177 | #define MP_DEV_WAIT MP_DEV_OP_MAX /* Wait for the lock */ | |
178 | ||
179 | /* | |
180 | * If the caller specifies an op value different than MP_DEV_WAIT, the | |
181 | * at386_io_lock function must return true if lock was successful else | |
182 | * false | |
183 | */ | |
184 | ||
185 | #define MP_DEV_OP_START 0 /* If lock busy, register a pending start op */ | |
186 | #define MP_DEV_OP_INTR 1 /* If lock busy, register a pending intr */ | |
187 | #define MP_DEV_OP_TIMEO 2 /* If lock busy, register a pending timeout */ | |
188 | #define MP_DEV_OP_CALLB 3 /* If lock busy, register a pending callback */ | |
189 | ||
190 | #else /* NCPUS > 1 */ | |
191 | #define at386_io_lock_state() | |
192 | #define at386_io_lock(op) (TRUE) | |
193 | #define at386_io_unlock() | |
55e303ae A |
194 | #define mp_trap_enter() |
195 | #define mp_trap_exit() | |
1c79356b | 196 | #include <i386/apic.h> |
1c79356b A |
197 | #endif /* NCPUS > 1 */ |
198 | ||
199 | #if MACH_RT | |
200 | #define _DISABLE_PREEMPTION(r) \ | |
9bccf70c | 201 | movl $ CPD_PREEMPTION_LEVEL,r ; \ |
1c79356b A |
202 | incl %gs:(r) |
203 | ||
204 | #define _ENABLE_PREEMPTION(r) \ | |
9bccf70c | 205 | movl $ CPD_PREEMPTION_LEVEL,r ; \ |
1c79356b A |
206 | decl %gs:(r) ; \ |
207 | jne 9f ; \ | |
208 | pushl %eax ; \ | |
209 | pushl %ecx ; \ | |
210 | pushl %edx ; \ | |
211 | call EXT(kernel_preempt_check) ; \ | |
212 | popl %edx ; \ | |
213 | popl %ecx ; \ | |
214 | popl %eax ; \ | |
215 | 9: | |
216 | ||
217 | #define _ENABLE_PREEMPTION_NO_CHECK(r) \ | |
9bccf70c | 218 | movl $ CPD_PREEMPTION_LEVEL,r ; \ |
1c79356b A |
219 | decl %gs:(r) |
220 | ||
221 | #if MACH_ASSERT | |
222 | #define DISABLE_PREEMPTION(r) \ | |
223 | pushl %eax; \ | |
224 | pushl %ecx; \ | |
225 | pushl %edx; \ | |
226 | call EXT(_disable_preemption); \ | |
227 | popl %edx; \ | |
228 | popl %ecx; \ | |
229 | popl %eax | |
230 | #define ENABLE_PREEMPTION(r) \ | |
231 | pushl %eax; \ | |
232 | pushl %ecx; \ | |
233 | pushl %edx; \ | |
234 | call EXT(_enable_preemption); \ | |
235 | popl %edx; \ | |
236 | popl %ecx; \ | |
237 | popl %eax | |
238 | #define ENABLE_PREEMPTION_NO_CHECK(r) \ | |
239 | pushl %eax; \ | |
240 | pushl %ecx; \ | |
241 | pushl %edx; \ | |
242 | call EXT(_enable_preemption_no_check); \ | |
243 | popl %edx; \ | |
244 | popl %ecx; \ | |
245 | popl %eax | |
246 | #if NCPUS > 1 | |
247 | #define MP_DISABLE_PREEMPTION(r) \ | |
248 | pushl %eax; \ | |
249 | pushl %ecx; \ | |
250 | pushl %edx; \ | |
251 | call EXT(_mp_disable_preemption); \ | |
252 | popl %edx; \ | |
253 | popl %ecx; \ | |
254 | popl %eax | |
255 | #define MP_ENABLE_PREEMPTION(r) \ | |
256 | pushl %eax; \ | |
257 | pushl %ecx; \ | |
258 | pushl %edx; \ | |
259 | call EXT(_mp_enable_preemption); \ | |
260 | popl %edx; \ | |
261 | popl %ecx; \ | |
262 | popl %eax | |
263 | #define MP_ENABLE_PREEMPTION_NO_CHECK(r) \ | |
264 | pushl %eax; \ | |
265 | pushl %ecx; \ | |
266 | pushl %edx; \ | |
267 | call EXT(_mp_enable_preemption_no_check); \ | |
268 | popl %edx; \ | |
269 | popl %ecx; \ | |
270 | popl %eax | |
271 | #else /* NCPUS > 1 */ | |
272 | #define MP_DISABLE_PREEMPTION(r) | |
273 | #define MP_ENABLE_PREEMPTION(r) | |
274 | #define MP_ENABLE_PREEMPTION_NO_CHECK(r) | |
275 | #endif /* NCPUS > 1 */ | |
276 | #else /* MACH_ASSERT */ | |
277 | #define DISABLE_PREEMPTION(r) _DISABLE_PREEMPTION(r) | |
278 | #define ENABLE_PREEMPTION(r) _ENABLE_PREEMPTION(r) | |
279 | #define ENABLE_PREEMPTION_NO_CHECK(r) _ENABLE_PREEMPTION_NO_CHECK(r) | |
280 | #if NCPUS > 1 | |
281 | #define MP_DISABLE_PREEMPTION(r) _DISABLE_PREEMPTION(r) | |
282 | #define MP_ENABLE_PREEMPTION(r) _ENABLE_PREEMPTION(r) | |
283 | #define MP_ENABLE_PREEMPTION_NO_CHECK(r) _ENABLE_PREEMPTION_NO_CHECK(r) | |
284 | #else /* NCPUS > 1 */ | |
285 | #define MP_DISABLE_PREEMPTION(r) | |
286 | #define MP_ENABLE_PREEMPTION(r) | |
287 | #define MP_ENABLE_PREEMPTION_NO_CHECK(r) | |
288 | #endif /* NCPUS > 1 */ | |
289 | #endif /* MACH_ASSERT */ | |
290 | ||
291 | #else /* MACH_RT */ | |
292 | #define DISABLE_PREEMPTION(r) | |
293 | #define ENABLE_PREEMPTION(r) | |
294 | #define ENABLE_PREEMPTION_NO_CHECK(r) | |
295 | #define MP_DISABLE_PREEMPTION(r) | |
296 | #define MP_ENABLE_PREEMPTION(r) | |
297 | #define MP_ENABLE_PREEMPTION_NO_CHECK(r) | |
298 | #endif /* MACH_RT */ | |
299 | ||
300 | #endif /* _I386AT_MP_H_ */ |