]>
Commit | Line | Data |
---|---|---|
1c79356b | 1 | /* |
91447636 | 2 | * Copyright (c) 2000-2005 Apple Computer, Inc. All rights reserved. |
1c79356b | 3 | * |
6601e61a | 4 | * @APPLE_LICENSE_HEADER_START@ |
1c79356b | 5 | * |
6601e61a 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. | |
8f6c56a5 | 11 | * |
6601e61a 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 | |
8f6c56a5 A |
14 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, |
15 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, | |
6601e61a 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. | |
8f6c56a5 | 19 | * |
6601e61a | 20 | * @APPLE_LICENSE_HEADER_END@ |
1c79356b A |
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 | */ | |
91447636 | 53 | #ifdef KERNEL_PRIVATE |
1c79356b A |
54 | |
55 | #ifndef _I386AT_MP_H_ | |
56 | #define _I386AT_MP_H_ | |
57 | ||
55e303ae A |
58 | #ifndef DEBUG |
59 | #include <debug.h> | |
60 | #endif | |
91447636 | 61 | //#define MP_DEBUG 1 |
55e303ae | 62 | |
1c79356b | 63 | #include <i386/apic.h> |
55e303ae A |
64 | #include <i386/mp_events.h> |
65 | ||
91447636 | 66 | #define LAPIC_ID_MAX (LAPIC_ID_MASK) |
55e303ae | 67 | |
91447636 | 68 | #define MAX_CPUS (LAPIC_ID_MAX + 1) |
55e303ae A |
69 | |
70 | #ifndef ASSEMBLER | |
91447636 A |
71 | #include <sys/cdefs.h> |
72 | #include <mach/boolean.h> | |
73 | #include <mach/kern_return.h> | |
74 | ||
75 | __BEGIN_DECLS | |
76 | ||
77 | extern kern_return_t intel_startCPU(int slot_num); | |
78 | extern void i386_init_slave(void); | |
79 | extern void smp_init(void); | |
80 | ||
81 | extern void cpu_interrupt(int cpu); | |
82 | ||
83 | extern void lapic_init(void); | |
84 | extern void lapic_shutdown(void); | |
85 | extern void lapic_smm_restore(void); | |
86 | extern boolean_t lapic_probe(void); | |
55e303ae | 87 | extern void lapic_dump(void); |
6601e61a | 88 | extern int lapic_interrupt(int interrupt, void *state); |
91447636 | 89 | extern void lapic_end_of_interrupt(void); |
55e303ae A |
90 | extern int lapic_to_cpu[]; |
91 | extern int cpu_to_lapic[]; | |
91447636 | 92 | extern int lapic_interrupt_base; |
55e303ae | 93 | extern void lapic_cpu_map(int lapic, int cpu_num); |
91447636 A |
94 | |
95 | extern void lapic_set_timer( | |
96 | boolean_t interrupt, | |
97 | lapic_timer_mode_t mode, | |
98 | lapic_timer_divide_t divisor, | |
99 | lapic_timer_count_t initial_count); | |
100 | ||
101 | extern void lapic_get_timer( | |
102 | lapic_timer_mode_t *mode, | |
103 | lapic_timer_divide_t *divisor, | |
104 | lapic_timer_count_t *initial_count, | |
105 | lapic_timer_count_t *current_count); | |
106 | ||
107 | typedef void (*i386_intr_func_t)(void *); | |
108 | extern void lapic_set_timer_func(i386_intr_func_t func); | |
109 | extern void lapic_set_pmi_func(i386_intr_func_t func); | |
110 | ||
111 | __END_DECLS | |
112 | ||
55e303ae | 113 | #endif /* ASSEMBLER */ |
1c79356b | 114 | |
55e303ae | 115 | #define CPU_NUMBER(r) \ |
91447636 A |
116 | movl %gs:CPU_NUMBER_GS,r |
117 | ||
118 | #define CPU_NUMBER_FROM_LAPIC(r) \ | |
55e303ae A |
119 | movl EXT(lapic_id),r; \ |
120 | movl 0(r),r; \ | |
121 | shrl $(LAPIC_ID_SHIFT),r; \ | |
122 | andl $(LAPIC_ID_MASK),r; \ | |
123 | movl EXT(lapic_to_cpu)(,r,4),r | |
1c79356b A |
124 | |
125 | ||
1c79356b A |
126 | /* word describing the reason for the interrupt, one per cpu */ |
127 | ||
128 | #ifndef ASSEMBLER | |
129 | #include <kern/lock.h> | |
91447636 A |
130 | |
131 | extern unsigned int real_ncpus; /* real number of cpus */ | |
132 | extern unsigned int max_ncpus; /* max number of cpus */ | |
1c79356b | 133 | decl_simple_lock_data(extern,kdb_lock) /* kdb lock */ |
91447636 A |
134 | |
135 | __BEGIN_DECLS | |
136 | ||
137 | extern void console_init(void); | |
138 | extern void *console_cpu_alloc(boolean_t boot_cpu); | |
139 | extern void console_cpu_free(void *console_buf); | |
1c79356b A |
140 | |
141 | extern int kdb_cpu; /* current cpu running kdb */ | |
142 | extern int kdb_debug; | |
6601e61a | 143 | extern int kdb_is_slave[]; |
1c79356b | 144 | extern int kdb_active[]; |
55e303ae A |
145 | |
146 | extern volatile boolean_t mp_kdp_trap; | |
91447636 A |
147 | extern void mp_kdp_enter(void); |
148 | extern void mp_kdp_exit(void); | |
55e303ae A |
149 | |
150 | /* | |
151 | * All cpu rendezvous: | |
152 | */ | |
6601e61a A |
153 | extern void mp_rendezvous(void (*setup_func)(void *), |
154 | void (*action_func)(void *), | |
155 | void (*teardown_func)(void *), | |
156 | void *arg); | |
55e303ae | 157 | |
91447636 A |
158 | __END_DECLS |
159 | ||
55e303ae A |
160 | #if MP_DEBUG |
161 | typedef struct { | |
162 | uint64_t time; | |
163 | int cpu; | |
164 | mp_event_t event; | |
165 | } cpu_signal_event_t; | |
166 | ||
167 | #define LOG_NENTRIES 100 | |
168 | typedef struct { | |
169 | uint64_t count[MP_LAST]; | |
170 | int next_entry; | |
171 | cpu_signal_event_t entry[LOG_NENTRIES]; | |
172 | } cpu_signal_event_log_t; | |
173 | ||
91447636 A |
174 | extern cpu_signal_event_log_t *cpu_signal[]; |
175 | extern cpu_signal_event_log_t *cpu_handle[]; | |
55e303ae A |
176 | |
177 | #define DBGLOG(log,_cpu,_event) { \ | |
91447636 A |
178 | boolean_t spl = ml_set_interrupts_enabled(FALSE); \ |
179 | cpu_signal_event_log_t *logp = log[cpu_number()]; \ | |
55e303ae A |
180 | int next = logp->next_entry; \ |
181 | cpu_signal_event_t *eventp = &logp->entry[next]; \ | |
55e303ae A |
182 | \ |
183 | logp->count[_event]++; \ | |
184 | \ | |
185 | eventp->time = rdtsc64(); \ | |
186 | eventp->cpu = _cpu; \ | |
187 | eventp->event = _event; \ | |
188 | if (next == (LOG_NENTRIES - 1)) \ | |
189 | logp->next_entry = 0; \ | |
190 | else \ | |
191 | logp->next_entry++; \ | |
192 | \ | |
193 | (void) ml_set_interrupts_enabled(spl); \ | |
194 | } | |
91447636 A |
195 | |
196 | #define DBGLOG_CPU_INIT(cpu) { \ | |
197 | cpu_signal_event_log_t **sig_logpp = &cpu_signal[cpu]; \ | |
198 | cpu_signal_event_log_t **hdl_logpp = &cpu_handle[cpu]; \ | |
199 | \ | |
200 | if (*sig_logpp == NULL && \ | |
201 | kmem_alloc(kernel_map, \ | |
202 | (vm_offset_t *) sig_logpp, \ | |
203 | sizeof(cpu_signal_event_log_t)) != KERN_SUCCESS)\ | |
204 | panic("DBGLOG_CPU_INIT cpu_signal allocation failed\n");\ | |
205 | bzero(*sig_logpp, sizeof(cpu_signal_event_log_t)); \ | |
206 | if (*hdl_logpp == NULL && \ | |
207 | kmem_alloc(kernel_map, \ | |
208 | (vm_offset_t *) hdl_logpp, \ | |
209 | sizeof(cpu_signal_event_log_t)) != KERN_SUCCESS)\ | |
210 | panic("DBGLOG_CPU_INIT cpu_handle allocation failed\n");\ | |
211 | bzero(*sig_logpp, sizeof(cpu_signal_event_log_t)); \ | |
212 | } | |
55e303ae A |
213 | #else /* MP_DEBUG */ |
214 | #define DBGLOG(log,_cpu,_event) | |
91447636 | 215 | #define DBGLOG_CPU_INIT(cpu) |
55e303ae A |
216 | #endif /* MP_DEBUG */ |
217 | ||
1c79356b A |
218 | #endif /* ASSEMBLER */ |
219 | ||
220 | #define i_bit(bit, word) ((long)(*(word)) & ((long)1 << (bit))) | |
221 | ||
222 | ||
223 | /* | |
224 | * Device driver synchronization. | |
225 | * | |
226 | * at386_io_lock(op) and at386_io_unlock() are called | |
227 | * by device drivers when accessing H/W. The underlying | |
228 | * Processing is machine dependant. But the op argument | |
229 | * to the at386_io_lock is generic | |
230 | */ | |
231 | ||
232 | #define MP_DEV_OP_MAX 4 | |
233 | #define MP_DEV_WAIT MP_DEV_OP_MAX /* Wait for the lock */ | |
234 | ||
235 | /* | |
236 | * If the caller specifies an op value different than MP_DEV_WAIT, the | |
237 | * at386_io_lock function must return true if lock was successful else | |
238 | * false | |
239 | */ | |
240 | ||
241 | #define MP_DEV_OP_START 0 /* If lock busy, register a pending start op */ | |
242 | #define MP_DEV_OP_INTR 1 /* If lock busy, register a pending intr */ | |
243 | #define MP_DEV_OP_TIMEO 2 /* If lock busy, register a pending timeout */ | |
244 | #define MP_DEV_OP_CALLB 3 /* If lock busy, register a pending callback */ | |
245 | ||
1c79356b | 246 | #if MACH_RT |
91447636 A |
247 | #define _DISABLE_PREEMPTION \ |
248 | incl %gs:CPU_PREEMPTION_LEVEL | |
1c79356b | 249 | |
91447636 A |
250 | #define _ENABLE_PREEMPTION \ |
251 | decl %gs:CPU_PREEMPTION_LEVEL ; \ | |
1c79356b A |
252 | jne 9f ; \ |
253 | pushl %eax ; \ | |
254 | pushl %ecx ; \ | |
255 | pushl %edx ; \ | |
256 | call EXT(kernel_preempt_check) ; \ | |
257 | popl %edx ; \ | |
258 | popl %ecx ; \ | |
259 | popl %eax ; \ | |
260 | 9: | |
261 | ||
91447636 A |
262 | #define _ENABLE_PREEMPTION_NO_CHECK \ |
263 | decl %gs:CPU_PREEMPTION_LEVEL | |
1c79356b A |
264 | |
265 | #if MACH_ASSERT | |
91447636 | 266 | #define DISABLE_PREEMPTION \ |
1c79356b A |
267 | pushl %eax; \ |
268 | pushl %ecx; \ | |
269 | pushl %edx; \ | |
270 | call EXT(_disable_preemption); \ | |
271 | popl %edx; \ | |
272 | popl %ecx; \ | |
273 | popl %eax | |
91447636 | 274 | #define ENABLE_PREEMPTION \ |
1c79356b A |
275 | pushl %eax; \ |
276 | pushl %ecx; \ | |
277 | pushl %edx; \ | |
278 | call EXT(_enable_preemption); \ | |
279 | popl %edx; \ | |
280 | popl %ecx; \ | |
281 | popl %eax | |
91447636 | 282 | #define ENABLE_PREEMPTION_NO_CHECK \ |
1c79356b A |
283 | pushl %eax; \ |
284 | pushl %ecx; \ | |
285 | pushl %edx; \ | |
286 | call EXT(_enable_preemption_no_check); \ | |
287 | popl %edx; \ | |
288 | popl %ecx; \ | |
289 | popl %eax | |
91447636 | 290 | #define MP_DISABLE_PREEMPTION \ |
1c79356b A |
291 | pushl %eax; \ |
292 | pushl %ecx; \ | |
293 | pushl %edx; \ | |
294 | call EXT(_mp_disable_preemption); \ | |
295 | popl %edx; \ | |
296 | popl %ecx; \ | |
297 | popl %eax | |
91447636 | 298 | #define MP_ENABLE_PREEMPTION \ |
1c79356b A |
299 | pushl %eax; \ |
300 | pushl %ecx; \ | |
301 | pushl %edx; \ | |
302 | call EXT(_mp_enable_preemption); \ | |
303 | popl %edx; \ | |
304 | popl %ecx; \ | |
305 | popl %eax | |
91447636 | 306 | #define MP_ENABLE_PREEMPTION_NO_CHECK \ |
1c79356b A |
307 | pushl %eax; \ |
308 | pushl %ecx; \ | |
309 | pushl %edx; \ | |
310 | call EXT(_mp_enable_preemption_no_check); \ | |
311 | popl %edx; \ | |
312 | popl %ecx; \ | |
313 | popl %eax | |
1c79356b | 314 | #else /* MACH_ASSERT */ |
91447636 A |
315 | #define DISABLE_PREEMPTION _DISABLE_PREEMPTION |
316 | #define ENABLE_PREEMPTION _ENABLE_PREEMPTION | |
317 | #define ENABLE_PREEMPTION_NO_CHECK _ENABLE_PREEMPTION_NO_CHECK | |
318 | #define MP_DISABLE_PREEMPTION _DISABLE_PREEMPTION | |
319 | #define MP_ENABLE_PREEMPTION _ENABLE_PREEMPTION | |
320 | #define MP_ENABLE_PREEMPTION_NO_CHECK _ENABLE_PREEMPTION_NO_CHECK | |
1c79356b A |
321 | #endif /* MACH_ASSERT */ |
322 | ||
323 | #else /* MACH_RT */ | |
91447636 A |
324 | #define DISABLE_PREEMPTION |
325 | #define ENABLE_PREEMPTION | |
326 | #define ENABLE_PREEMPTION_NO_CHECK | |
327 | #define MP_DISABLE_PREEMPTION | |
328 | #define MP_ENABLE_PREEMPTION | |
329 | #define MP_ENABLE_PREEMPTION_NO_CHECK | |
1c79356b A |
330 | #endif /* MACH_RT */ |
331 | ||
332 | #endif /* _I386AT_MP_H_ */ | |
91447636 A |
333 | |
334 | #endif /* KERNEL_PRIVATE */ |