2 * Copyright (c) 2000-2005 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
21 * @APPLE_LICENSE_HEADER_END@
27 * Mach Operating System
28 * Copyright (c) 1991,1990 Carnegie Mellon University
29 * All Rights Reserved.
31 * Permission to use, copy, modify and distribute this software and its
32 * documentation is hereby granted, provided that both the copyright
33 * notice and this permission notice appear in all copies of the
34 * software, derivative works or modified versions, and any portions
35 * thereof, and that both notices appear in supporting documentation.
37 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
38 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
39 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
41 * Carnegie Mellon requests users of this software to return to
43 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
44 * School of Computer Science
45 * Carnegie Mellon University
46 * Pittsburgh PA 15213-3890
48 * any improvements or extensions that they make and grant Carnegie Mellon
49 * the rights to redistribute these changes.
64 #include <i386/apic.h>
65 #include <i386/mp_events.h>
67 #define LAPIC_ID_MAX (LAPIC_ID_MASK)
69 #define MAX_CPUS (LAPIC_ID_MAX + 1)
72 #include <sys/cdefs.h>
73 #include <mach/boolean.h>
74 #include <mach/kern_return.h>
78 extern kern_return_t
intel_startCPU(int slot_num
);
79 extern void i386_init_slave(void);
80 extern void smp_init(void);
82 extern void cpu_interrupt(int cpu
);
84 extern void lapic_init(void);
85 extern void lapic_shutdown(void);
86 extern void lapic_smm_restore(void);
87 extern boolean_t
lapic_probe(void);
88 extern void lapic_dump(void);
89 extern int lapic_interrupt(int interrupt
, void *state
);
90 extern void lapic_end_of_interrupt(void);
91 extern int lapic_to_cpu
[];
92 extern int cpu_to_lapic
[];
93 extern int lapic_interrupt_base
;
94 extern void lapic_cpu_map(int lapic
, int cpu_num
);
96 extern void lapic_set_timer(
98 lapic_timer_mode_t mode
,
99 lapic_timer_divide_t divisor
,
100 lapic_timer_count_t initial_count
);
102 extern void lapic_get_timer(
103 lapic_timer_mode_t
*mode
,
104 lapic_timer_divide_t
*divisor
,
105 lapic_timer_count_t
*initial_count
,
106 lapic_timer_count_t
*current_count
);
108 typedef void (*i386_intr_func_t
)(void *);
109 extern void lapic_set_timer_func(i386_intr_func_t func
);
110 extern void lapic_set_pmi_func(i386_intr_func_t func
);
114 #endif /* ASSEMBLER */
116 #define CPU_NUMBER(r) \
117 movl %gs:CPU_NUMBER_GS,r
119 #define CPU_NUMBER_FROM_LAPIC(r) \
120 movl EXT(lapic_id),r; \
122 shrl $(LAPIC_ID_SHIFT),r; \
123 andl $(LAPIC_ID_MASK),r; \
124 movl EXT(lapic_to_cpu)(,r,4),r
127 /* word describing the reason for the interrupt, one per cpu */
130 #include <kern/lock.h>
132 extern unsigned int real_ncpus
; /* real number of cpus */
133 extern unsigned int max_ncpus
; /* max number of cpus */
134 decl_simple_lock_data(extern,kdb_lock
) /* kdb lock */
138 extern void console_init(void);
139 extern void *console_cpu_alloc(boolean_t boot_cpu
);
140 extern void console_cpu_free(void *console_buf
);
142 extern int kdb_cpu
; /* current cpu running kdb */
143 extern int kdb_debug
;
144 extern int kdb_is_slave
[];
145 extern int kdb_active
[];
147 extern volatile boolean_t mp_kdp_trap
;
148 extern void mp_kdp_enter(void);
149 extern void mp_kdp_exit(void);
152 * All cpu rendezvous:
154 extern void mp_rendezvous(void (*setup_func
)(void *),
155 void (*action_func
)(void *),
156 void (*teardown_func
)(void *),
166 } cpu_signal_event_t
;
168 #define LOG_NENTRIES 100
170 uint64_t count
[MP_LAST
];
172 cpu_signal_event_t entry
[LOG_NENTRIES
];
173 } cpu_signal_event_log_t
;
175 extern cpu_signal_event_log_t
*cpu_signal
[];
176 extern cpu_signal_event_log_t
*cpu_handle
[];
178 #define DBGLOG(log,_cpu,_event) { \
179 boolean_t spl = ml_set_interrupts_enabled(FALSE); \
180 cpu_signal_event_log_t *logp = log[cpu_number()]; \
181 int next = logp->next_entry; \
182 cpu_signal_event_t *eventp = &logp->entry[next]; \
184 logp->count[_event]++; \
186 eventp->time = rdtsc64(); \
187 eventp->cpu = _cpu; \
188 eventp->event = _event; \
189 if (next == (LOG_NENTRIES - 1)) \
190 logp->next_entry = 0; \
192 logp->next_entry++; \
194 (void) ml_set_interrupts_enabled(spl); \
197 #define DBGLOG_CPU_INIT(cpu) { \
198 cpu_signal_event_log_t **sig_logpp = &cpu_signal[cpu]; \
199 cpu_signal_event_log_t **hdl_logpp = &cpu_handle[cpu]; \
201 if (*sig_logpp == NULL && \
202 kmem_alloc(kernel_map, \
203 (vm_offset_t *) sig_logpp, \
204 sizeof(cpu_signal_event_log_t)) != KERN_SUCCESS)\
205 panic("DBGLOG_CPU_INIT cpu_signal allocation failed\n");\
206 bzero(*sig_logpp, sizeof(cpu_signal_event_log_t)); \
207 if (*hdl_logpp == NULL && \
208 kmem_alloc(kernel_map, \
209 (vm_offset_t *) hdl_logpp, \
210 sizeof(cpu_signal_event_log_t)) != KERN_SUCCESS)\
211 panic("DBGLOG_CPU_INIT cpu_handle allocation failed\n");\
212 bzero(*sig_logpp, sizeof(cpu_signal_event_log_t)); \
215 #define DBGLOG(log,_cpu,_event)
216 #define DBGLOG_CPU_INIT(cpu)
217 #endif /* MP_DEBUG */
219 #endif /* ASSEMBLER */
221 #define i_bit(bit, word) ((long)(*(word)) & ((long)1 << (bit)))
225 * Device driver synchronization.
227 * at386_io_lock(op) and at386_io_unlock() are called
228 * by device drivers when accessing H/W. The underlying
229 * Processing is machine dependant. But the op argument
230 * to the at386_io_lock is generic
233 #define MP_DEV_OP_MAX 4
234 #define MP_DEV_WAIT MP_DEV_OP_MAX /* Wait for the lock */
237 * If the caller specifies an op value different than MP_DEV_WAIT, the
238 * at386_io_lock function must return true if lock was successful else
242 #define MP_DEV_OP_START 0 /* If lock busy, register a pending start op */
243 #define MP_DEV_OP_INTR 1 /* If lock busy, register a pending intr */
244 #define MP_DEV_OP_TIMEO 2 /* If lock busy, register a pending timeout */
245 #define MP_DEV_OP_CALLB 3 /* If lock busy, register a pending callback */
248 #define _DISABLE_PREEMPTION \
249 incl %gs:CPU_PREEMPTION_LEVEL
251 #define _ENABLE_PREEMPTION \
252 decl %gs:CPU_PREEMPTION_LEVEL ; \
257 call EXT(kernel_preempt_check) ; \
263 #define _ENABLE_PREEMPTION_NO_CHECK \
264 decl %gs:CPU_PREEMPTION_LEVEL
267 #define DISABLE_PREEMPTION \
271 call EXT(_disable_preemption); \
275 #define ENABLE_PREEMPTION \
279 call EXT(_enable_preemption); \
283 #define ENABLE_PREEMPTION_NO_CHECK \
287 call EXT(_enable_preemption_no_check); \
291 #define MP_DISABLE_PREEMPTION \
295 call EXT(_mp_disable_preemption); \
299 #define MP_ENABLE_PREEMPTION \
303 call EXT(_mp_enable_preemption); \
307 #define MP_ENABLE_PREEMPTION_NO_CHECK \
311 call EXT(_mp_enable_preemption_no_check); \
315 #else /* MACH_ASSERT */
316 #define DISABLE_PREEMPTION _DISABLE_PREEMPTION
317 #define ENABLE_PREEMPTION _ENABLE_PREEMPTION
318 #define ENABLE_PREEMPTION_NO_CHECK _ENABLE_PREEMPTION_NO_CHECK
319 #define MP_DISABLE_PREEMPTION _DISABLE_PREEMPTION
320 #define MP_ENABLE_PREEMPTION _ENABLE_PREEMPTION
321 #define MP_ENABLE_PREEMPTION_NO_CHECK _ENABLE_PREEMPTION_NO_CHECK
322 #endif /* MACH_ASSERT */
325 #define DISABLE_PREEMPTION
326 #define ENABLE_PREEMPTION
327 #define ENABLE_PREEMPTION_NO_CHECK
328 #define MP_DISABLE_PREEMPTION
329 #define MP_ENABLE_PREEMPTION
330 #define MP_ENABLE_PREEMPTION_NO_CHECK
333 #endif /* _I386AT_MP_H_ */
335 #endif /* KERNEL_PRIVATE */