xref: /titanic_50/usr/src/uts/i86pc/io/pcplusmp/apic_common.c (revision 461686c359e383739b8e0d23c68520a0e2e2c361)
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 (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 
22 /*
23  * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
24  */
25 
26 /*
27  * PSMI 1.1 extensions are supported only in 2.6 and later versions.
28  * PSMI 1.2 extensions are supported only in 2.7 and later versions.
29  * PSMI 1.3 and 1.4 extensions are supported in Solaris 10.
30  * PSMI 1.5 extensions are supported in Solaris Nevada.
31  * PSMI 1.6 extensions are supported in Solaris Nevada.
32  * PSMI 1.7 extensions are supported in Solaris Nevada.
33  */
34 #define	PSMI_1_7
35 
36 #include <sys/processor.h>
37 #include <sys/time.h>
38 #include <sys/psm.h>
39 #include <sys/smp_impldefs.h>
40 #include <sys/cram.h>
41 #include <sys/acpi/acpi.h>
42 #include <sys/acpica.h>
43 #include <sys/psm_common.h>
44 #include <sys/apic.h>
45 #include <sys/pit.h>
46 #include <sys/ddi.h>
47 #include <sys/sunddi.h>
48 #include <sys/ddi_impldefs.h>
49 #include <sys/pci.h>
50 #include <sys/promif.h>
51 #include <sys/x86_archext.h>
52 #include <sys/cpc_impl.h>
53 #include <sys/uadmin.h>
54 #include <sys/panic.h>
55 #include <sys/debug.h>
56 #include <sys/archsystm.h>
57 #include <sys/trap.h>
58 #include <sys/machsystm.h>
59 #include <sys/sysmacros.h>
60 #include <sys/cpuvar.h>
61 #include <sys/rm_platter.h>
62 #include <sys/privregs.h>
63 #include <sys/note.h>
64 #include <sys/pci_intr_lib.h>
65 #include <sys/spl.h>
66 #include <sys/clock.h>
67 #include <sys/dditypes.h>
68 #include <sys/sunddi.h>
69 #include <sys/x_call.h>
70 #include <sys/reboot.h>
71 #include <sys/hpet.h>
72 #include <sys/apic_common.h>
73 #include <sys/apic_timer.h>
74 
75 static void	apic_record_ioapic_rdt(void *intrmap_private,
76 		    ioapic_rdt_t *irdt);
77 static void	apic_record_msi(void *intrmap_private, msi_regs_t *mregs);
78 
79 /*
80  * Common routines between pcplusmp & apix (taken from apic.c).
81  */
82 
83 int	apic_clkinit(int);
84 hrtime_t apic_gethrtime(void);
85 void	apic_send_ipi(int, int);
86 void	apic_set_idlecpu(processorid_t);
87 void	apic_unset_idlecpu(processorid_t);
88 void	apic_shutdown(int, int);
89 void	apic_preshutdown(int, int);
90 processorid_t	apic_get_next_processorid(processorid_t);
91 
92 hrtime_t apic_gettime();
93 
94 enum apic_ioapic_method_type apix_mul_ioapic_method = APIC_MUL_IOAPIC_PCPLUSMP;
95 
96 /* Now the ones for Dynamic Interrupt distribution */
97 int	apic_enable_dynamic_migration = 0;
98 
99 /* maximum loop count when sending Start IPIs. */
100 int apic_sipi_max_loop_count = 0x1000;
101 
102 /*
103  * These variables are frequently accessed in apic_intr_enter(),
104  * apic_intr_exit and apic_setspl, so group them together
105  */
106 volatile uint32_t *apicadr =  NULL;	/* virtual addr of local APIC	*/
107 int apic_setspl_delay = 1;		/* apic_setspl - delay enable	*/
108 int apic_clkvect;
109 
110 /* vector at which error interrupts come in */
111 int apic_errvect;
112 int apic_enable_error_intr = 1;
113 int apic_error_display_delay = 100;
114 
115 /* vector at which performance counter overflow interrupts come in */
116 int apic_cpcovf_vect;
117 int apic_enable_cpcovf_intr = 1;
118 
119 /* vector at which CMCI interrupts come in */
120 int apic_cmci_vect;
121 extern int cmi_enable_cmci;
122 extern void cmi_cmci_trap(void);
123 
124 kmutex_t cmci_cpu_setup_lock;	/* protects cmci_cpu_setup_registered */
125 int cmci_cpu_setup_registered;
126 
127 /* number of CPUs in power-on transition state */
128 static int apic_poweron_cnt = 0;
129 lock_t apic_mode_switch_lock;
130 
131 /*
132  * Patchable global variables.
133  */
134 int	apic_forceload = 0;
135 
136 int	apic_coarse_hrtime = 1;		/* 0 - use accurate slow gethrtime() */
137 
138 int	apic_flat_model = 0;		/* 0 - clustered. 1 - flat */
139 int	apic_panic_on_nmi = 0;
140 int	apic_panic_on_apic_error = 0;
141 
142 int	apic_verbose = 0;	/* 0x1ff */
143 
144 #ifdef DEBUG
145 int	apic_debug = 0;
146 int	apic_restrict_vector = 0;
147 
148 int	apic_debug_msgbuf[APIC_DEBUG_MSGBUFSIZE];
149 int	apic_debug_msgbufindex = 0;
150 
151 #endif /* DEBUG */
152 
153 uint_t apic_nticks = 0;
154 uint_t apic_skipped_redistribute = 0;
155 
156 uint_t last_count_read = 0;
157 lock_t	apic_gethrtime_lock;
158 volatile int	apic_hrtime_stamp = 0;
159 volatile hrtime_t apic_nsec_since_boot = 0;
160 
161 static	hrtime_t	apic_last_hrtime = 0;
162 int		apic_hrtime_error = 0;
163 int		apic_remote_hrterr = 0;
164 int		apic_num_nmis = 0;
165 int		apic_apic_error = 0;
166 int		apic_num_apic_errors = 0;
167 int		apic_num_cksum_errors = 0;
168 
169 int	apic_error = 0;
170 
171 static	int	apic_cmos_ssb_set = 0;
172 
173 /* use to make sure only one cpu handles the nmi */
174 lock_t	apic_nmi_lock;
175 /* use to make sure only one cpu handles the error interrupt */
176 lock_t	apic_error_lock;
177 
178 static	struct {
179 	uchar_t	cntl;
180 	uchar_t	data;
181 } aspen_bmc[] = {
182 	{ CC_SMS_WR_START,	0x18 },		/* NetFn/LUN */
183 	{ CC_SMS_WR_NEXT,	0x24 },		/* Cmd SET_WATCHDOG_TIMER */
184 	{ CC_SMS_WR_NEXT,	0x84 },		/* DataByte 1: SMS/OS no log */
185 	{ CC_SMS_WR_NEXT,	0x2 },		/* DataByte 2: Power Down */
186 	{ CC_SMS_WR_NEXT,	0x0 },		/* DataByte 3: no pre-timeout */
187 	{ CC_SMS_WR_NEXT,	0x0 },		/* DataByte 4: timer expir. */
188 	{ CC_SMS_WR_NEXT,	0xa },		/* DataByte 5: init countdown */
189 	{ CC_SMS_WR_END,	0x0 },		/* DataByte 6: init countdown */
190 
191 	{ CC_SMS_WR_START,	0x18 },		/* NetFn/LUN */
192 	{ CC_SMS_WR_END,	0x22 }		/* Cmd RESET_WATCHDOG_TIMER */
193 };
194 
195 static	struct {
196 	int	port;
197 	uchar_t	data;
198 } sitka_bmc[] = {
199 	{ SMS_COMMAND_REGISTER,	SMS_WRITE_START },
200 	{ SMS_DATA_REGISTER,	0x18 },		/* NetFn/LUN */
201 	{ SMS_DATA_REGISTER,	0x24 },		/* Cmd SET_WATCHDOG_TIMER */
202 	{ SMS_DATA_REGISTER,	0x84 },		/* DataByte 1: SMS/OS no log */
203 	{ SMS_DATA_REGISTER,	0x2 },		/* DataByte 2: Power Down */
204 	{ SMS_DATA_REGISTER,	0x0 },		/* DataByte 3: no pre-timeout */
205 	{ SMS_DATA_REGISTER,	0x0 },		/* DataByte 4: timer expir. */
206 	{ SMS_DATA_REGISTER,	0xa },		/* DataByte 5: init countdown */
207 	{ SMS_COMMAND_REGISTER,	SMS_WRITE_END },
208 	{ SMS_DATA_REGISTER,	0x0 },		/* DataByte 6: init countdown */
209 
210 	{ SMS_COMMAND_REGISTER,	SMS_WRITE_START },
211 	{ SMS_DATA_REGISTER,	0x18 },		/* NetFn/LUN */
212 	{ SMS_COMMAND_REGISTER,	SMS_WRITE_END },
213 	{ SMS_DATA_REGISTER,	0x22 }		/* Cmd RESET_WATCHDOG_TIMER */
214 };
215 
216 /* Patchable global variables. */
217 int		apic_kmdb_on_nmi = 0;		/* 0 - no, 1 - yes enter kmdb */
218 uint32_t	apic_divide_reg_init = 0;	/* 0 - divide by 2 */
219 
220 /* default apic ops without interrupt remapping */
221 static apic_intrmap_ops_t apic_nointrmap_ops = {
222 	(int (*)(int))return_instr,
223 	(void (*)(int))return_instr,
224 	(void (*)(void **, dev_info_t *, uint16_t, int, uchar_t))return_instr,
225 	(void (*)(void *, void *, uint16_t, int))return_instr,
226 	(void (*)(void **))return_instr,
227 	apic_record_ioapic_rdt,
228 	apic_record_msi,
229 };
230 
231 apic_intrmap_ops_t *apic_vt_ops = &apic_nointrmap_ops;
232 apic_cpus_info_t	*apic_cpus = NULL;
233 cpuset_t	apic_cpumask;
234 uint_t		apic_picinit_called;
235 
236 /* Flag to indicate that we need to shut down all processors */
237 static uint_t	apic_shutdown_processors;
238 
239 /*
240  * Probe the ioapic method for apix module. Called in apic_probe_common()
241  */
242 int
243 apic_ioapic_method_probe()
244 {
245 	if (apix_enable == 0)
246 		return (PSM_SUCCESS);
247 
248 	/*
249 	 * Set IOAPIC EOI handling method. The priority from low to high is:
250 	 * 	1. IOxAPIC: with EOI register
251 	 * 	2. IOMMU interrupt mapping
252 	 *	3. Mask-Before-EOI method for systems without boot
253 	 *	interrupt routing, such as systems with only one IOAPIC;
254 	 *	NVIDIA CK8-04/MCP55 systems; systems with bridge solution
255 	 *	which disables the boot interrupt routing already.
256 	 * 	4. Directed EOI
257 	 */
258 	if (apic_io_ver[0] >= 0x20)
259 		apix_mul_ioapic_method = APIC_MUL_IOAPIC_IOXAPIC;
260 	if ((apic_io_max == 1) || (apic_nvidia_io_max == apic_io_max))
261 		apix_mul_ioapic_method = APIC_MUL_IOAPIC_MASK;
262 	if (apic_directed_EOI_supported())
263 		apix_mul_ioapic_method = APIC_MUL_IOAPIC_DEOI;
264 
265 	/* fall back to pcplusmp */
266 	if (apix_mul_ioapic_method == APIC_MUL_IOAPIC_PCPLUSMP) {
267 		/* make sure apix is after pcplusmp in /etc/mach */
268 		apix_enable = 0; /* go ahead with pcplusmp install next */
269 		return (PSM_FAILURE);
270 	}
271 
272 	return (PSM_SUCCESS);
273 }
274 
275 /*
276  * handler for APIC Error interrupt. Just print a warning and continue
277  */
278 int
279 apic_error_intr()
280 {
281 	uint_t	error0, error1, error;
282 	uint_t	i;
283 
284 	/*
285 	 * We need to write before read as per 7.4.17 of system prog manual.
286 	 * We do both and or the results to be safe
287 	 */
288 	error0 = apic_reg_ops->apic_read(APIC_ERROR_STATUS);
289 	apic_reg_ops->apic_write(APIC_ERROR_STATUS, 0);
290 	error1 = apic_reg_ops->apic_read(APIC_ERROR_STATUS);
291 	error = error0 | error1;
292 
293 	/*
294 	 * Clear the APIC error status (do this on all cpus that enter here)
295 	 * (two writes are required due to the semantics of accessing the
296 	 * error status register.)
297 	 */
298 	apic_reg_ops->apic_write(APIC_ERROR_STATUS, 0);
299 	apic_reg_ops->apic_write(APIC_ERROR_STATUS, 0);
300 
301 	/*
302 	 * Prevent more than 1 CPU from handling error interrupt causing
303 	 * double printing (interleave of characters from multiple
304 	 * CPU's when using prom_printf)
305 	 */
306 	if (lock_try(&apic_error_lock) == 0)
307 		return (error ? DDI_INTR_CLAIMED : DDI_INTR_UNCLAIMED);
308 	if (error) {
309 #if	DEBUG
310 		if (apic_debug)
311 			debug_enter("pcplusmp: APIC Error interrupt received");
312 #endif /* DEBUG */
313 		if (apic_panic_on_apic_error)
314 			cmn_err(CE_PANIC,
315 			    "APIC Error interrupt on CPU %d. Status = %x",
316 			    psm_get_cpu_id(), error);
317 		else {
318 			if ((error & ~APIC_CS_ERRORS) == 0) {
319 				/* cksum error only */
320 				apic_error |= APIC_ERR_APIC_ERROR;
321 				apic_apic_error |= error;
322 				apic_num_apic_errors++;
323 				apic_num_cksum_errors++;
324 			} else {
325 				/*
326 				 * prom_printf is the best shot we have of
327 				 * something which is problem free from
328 				 * high level/NMI type of interrupts
329 				 */
330 				prom_printf("APIC Error interrupt on CPU %d. "
331 				    "Status 0 = %x, Status 1 = %x\n",
332 				    psm_get_cpu_id(), error0, error1);
333 				apic_error |= APIC_ERR_APIC_ERROR;
334 				apic_apic_error |= error;
335 				apic_num_apic_errors++;
336 				for (i = 0; i < apic_error_display_delay; i++) {
337 					tenmicrosec();
338 				}
339 				/*
340 				 * provide more delay next time limited to
341 				 * roughly 1 clock tick time
342 				 */
343 				if (apic_error_display_delay < 500)
344 					apic_error_display_delay *= 2;
345 			}
346 		}
347 		lock_clear(&apic_error_lock);
348 		return (DDI_INTR_CLAIMED);
349 	} else {
350 		lock_clear(&apic_error_lock);
351 		return (DDI_INTR_UNCLAIMED);
352 	}
353 }
354 
355 /*
356  * Turn off the mask bit in the performance counter Local Vector Table entry.
357  */
358 void
359 apic_cpcovf_mask_clear(void)
360 {
361 	apic_reg_ops->apic_write(APIC_PCINT_VECT,
362 	    (apic_reg_ops->apic_read(APIC_PCINT_VECT) & ~APIC_LVT_MASK));
363 }
364 
365 /*ARGSUSED*/
366 static int
367 apic_cmci_enable(xc_arg_t arg1, xc_arg_t arg2, xc_arg_t arg3)
368 {
369 	apic_reg_ops->apic_write(APIC_CMCI_VECT, apic_cmci_vect);
370 	return (0);
371 }
372 
373 /*ARGSUSED*/
374 static int
375 apic_cmci_disable(xc_arg_t arg1, xc_arg_t arg2, xc_arg_t arg3)
376 {
377 	apic_reg_ops->apic_write(APIC_CMCI_VECT, apic_cmci_vect | AV_MASK);
378 	return (0);
379 }
380 
381 /*ARGSUSED*/
382 int
383 cmci_cpu_setup(cpu_setup_t what, int cpuid, void *arg)
384 {
385 	cpuset_t	cpu_set;
386 
387 	CPUSET_ONLY(cpu_set, cpuid);
388 
389 	switch (what) {
390 		case CPU_ON:
391 			xc_call(NULL, NULL, NULL, CPUSET2BV(cpu_set),
392 			    (xc_func_t)apic_cmci_enable);
393 			break;
394 
395 		case CPU_OFF:
396 			xc_call(NULL, NULL, NULL, CPUSET2BV(cpu_set),
397 			    (xc_func_t)apic_cmci_disable);
398 			break;
399 
400 		default:
401 			break;
402 	}
403 
404 	return (0);
405 }
406 
407 static void
408 apic_disable_local_apic(void)
409 {
410 	apic_reg_ops->apic_write_task_reg(APIC_MASK_ALL);
411 	apic_reg_ops->apic_write(APIC_LOCAL_TIMER, AV_MASK);
412 
413 	/* local intr reg 0 */
414 	apic_reg_ops->apic_write(APIC_INT_VECT0, AV_MASK);
415 
416 	/* disable NMI */
417 	apic_reg_ops->apic_write(APIC_INT_VECT1, AV_MASK);
418 
419 	/* and error interrupt */
420 	apic_reg_ops->apic_write(APIC_ERR_VECT, AV_MASK);
421 
422 	/* and perf counter intr */
423 	apic_reg_ops->apic_write(APIC_PCINT_VECT, AV_MASK);
424 
425 	apic_reg_ops->apic_write(APIC_SPUR_INT_REG, APIC_SPUR_INTR);
426 }
427 
428 static void
429 apic_cpu_send_SIPI(processorid_t cpun, boolean_t start)
430 {
431 	int		loop_count;
432 	uint32_t	vector;
433 	uint_t		apicid;
434 	ulong_t		iflag;
435 
436 	apicid =  apic_cpus[cpun].aci_local_id;
437 
438 	/*
439 	 * Interrupts on current CPU will be disabled during the
440 	 * steps in order to avoid unwanted side effects from
441 	 * executing interrupt handlers on a problematic BIOS.
442 	 */
443 	iflag = intr_clear();
444 
445 	if (start) {
446 		outb(CMOS_ADDR, SSB);
447 		outb(CMOS_DATA, BIOS_SHUTDOWN);
448 	}
449 
450 	/*
451 	 * According to X2APIC specification in section '2.3.5.1' of
452 	 * Interrupt Command Register Semantics, the semantics of
453 	 * programming the Interrupt Command Register to dispatch an interrupt
454 	 * is simplified. A single MSR write to the 64-bit ICR is required
455 	 * for dispatching an interrupt. Specifically, with the 64-bit MSR
456 	 * interface to ICR, system software is not required to check the
457 	 * status of the delivery status bit prior to writing to the ICR
458 	 * to send an IPI. With the removal of the Delivery Status bit,
459 	 * system software no longer has a reason to read the ICR. It remains
460 	 * readable only to aid in debugging.
461 	 */
462 #ifdef	DEBUG
463 	APIC_AV_PENDING_SET();
464 #else
465 	if (apic_mode == LOCAL_APIC) {
466 		APIC_AV_PENDING_SET();
467 	}
468 #endif /* DEBUG */
469 
470 	/* for integrated - make sure there is one INIT IPI in buffer */
471 	/* for external - it will wake up the cpu */
472 	apic_reg_ops->apic_write_int_cmd(apicid, AV_ASSERT | AV_RESET);
473 
474 	/* If only 1 CPU is installed, PENDING bit will not go low */
475 	for (loop_count = apic_sipi_max_loop_count; loop_count; loop_count--) {
476 		if (apic_mode == LOCAL_APIC &&
477 		    apic_reg_ops->apic_read(APIC_INT_CMD1) & AV_PENDING)
478 			apic_ret();
479 		else
480 			break;
481 	}
482 
483 	apic_reg_ops->apic_write_int_cmd(apicid, AV_DEASSERT | AV_RESET);
484 	drv_usecwait(20000);		/* 20 milli sec */
485 
486 	if (apic_cpus[cpun].aci_local_ver >= APIC_INTEGRATED_VERS) {
487 		/* integrated apic */
488 
489 		vector = (rm_platter_pa >> MMU_PAGESHIFT) &
490 		    (APIC_VECTOR_MASK | APIC_IPL_MASK);
491 
492 		/* to offset the INIT IPI queue up in the buffer */
493 		apic_reg_ops->apic_write_int_cmd(apicid, vector | AV_STARTUP);
494 		drv_usecwait(200);		/* 20 micro sec */
495 
496 		/*
497 		 * send the second SIPI (Startup IPI) as recommended by Intel
498 		 * software development manual.
499 		 */
500 		apic_reg_ops->apic_write_int_cmd(apicid, vector | AV_STARTUP);
501 		drv_usecwait(200);	/* 20 micro sec */
502 	}
503 
504 	intr_restore(iflag);
505 }
506 
507 /*ARGSUSED1*/
508 int
509 apic_cpu_start(processorid_t cpun, caddr_t arg)
510 {
511 	ASSERT(MUTEX_HELD(&cpu_lock));
512 
513 	if (!apic_cpu_in_range(cpun)) {
514 		return (EINVAL);
515 	}
516 
517 	/*
518 	 * Switch to apic_common_send_ipi for safety during starting other CPUs.
519 	 */
520 	if (apic_mode == LOCAL_X2APIC) {
521 		apic_switch_ipi_callback(B_TRUE);
522 	}
523 
524 	apic_cmos_ssb_set = 1;
525 	apic_cpu_send_SIPI(cpun, B_TRUE);
526 
527 	return (0);
528 }
529 
530 /*
531  * Put CPU into halted state with interrupts disabled.
532  */
533 /*ARGSUSED1*/
534 int
535 apic_cpu_stop(processorid_t cpun, caddr_t arg)
536 {
537 	int		rc;
538 	cpu_t 		*cp;
539 	extern cpuset_t cpu_ready_set;
540 	extern void cpu_idle_intercept_cpu(cpu_t *cp);
541 
542 	ASSERT(MUTEX_HELD(&cpu_lock));
543 
544 	if (!apic_cpu_in_range(cpun)) {
545 		return (EINVAL);
546 	}
547 	if (apic_cpus[cpun].aci_local_ver < APIC_INTEGRATED_VERS) {
548 		return (ENOTSUP);
549 	}
550 
551 	cp = cpu_get(cpun);
552 	ASSERT(cp != NULL);
553 	ASSERT((cp->cpu_flags & CPU_OFFLINE) != 0);
554 	ASSERT((cp->cpu_flags & CPU_QUIESCED) != 0);
555 	ASSERT((cp->cpu_flags & CPU_ENABLE) == 0);
556 
557 	/* Clear CPU_READY flag to disable cross calls. */
558 	cp->cpu_flags &= ~CPU_READY;
559 	CPUSET_ATOMIC_DEL(cpu_ready_set, cpun);
560 	rc = xc_flush_cpu(cp);
561 	if (rc != 0) {
562 		CPUSET_ATOMIC_ADD(cpu_ready_set, cpun);
563 		cp->cpu_flags |= CPU_READY;
564 		return (rc);
565 	}
566 
567 	/* Intercept target CPU at a safe point before powering it off. */
568 	cpu_idle_intercept_cpu(cp);
569 
570 	apic_cpu_send_SIPI(cpun, B_FALSE);
571 	cp->cpu_flags &= ~CPU_RUNNING;
572 
573 	return (0);
574 }
575 
576 int
577 apic_cpu_ops(psm_cpu_request_t *reqp)
578 {
579 	if (reqp == NULL) {
580 		return (EINVAL);
581 	}
582 
583 	switch (reqp->pcr_cmd) {
584 	case PSM_CPU_ADD:
585 		return (apic_cpu_add(reqp));
586 
587 	case PSM_CPU_REMOVE:
588 		return (apic_cpu_remove(reqp));
589 
590 	case PSM_CPU_STOP:
591 		return (apic_cpu_stop(reqp->req.cpu_stop.cpuid,
592 		    reqp->req.cpu_stop.ctx));
593 
594 	default:
595 		return (ENOTSUP);
596 	}
597 }
598 
599 #ifdef	DEBUG
600 int	apic_break_on_cpu = 9;
601 int	apic_stretch_interrupts = 0;
602 int	apic_stretch_ISR = 1 << 3;	/* IPL of 3 matches nothing now */
603 #endif /* DEBUG */
604 
605 /*
606  * generates an interprocessor interrupt to another CPU. Any changes made to
607  * this routine must be accompanied by similar changes to
608  * apic_common_send_ipi().
609  */
610 void
611 apic_send_ipi(int cpun, int ipl)
612 {
613 	int vector;
614 	ulong_t flag;
615 
616 	vector = apic_resv_vector[ipl];
617 
618 	ASSERT((vector >= APIC_BASE_VECT) && (vector <= APIC_SPUR_INTR));
619 
620 	flag = intr_clear();
621 
622 	APIC_AV_PENDING_SET();
623 
624 	apic_reg_ops->apic_write_int_cmd(apic_cpus[cpun].aci_local_id,
625 	    vector);
626 
627 	intr_restore(flag);
628 }
629 
630 
631 /*ARGSUSED*/
632 void
633 apic_set_idlecpu(processorid_t cpun)
634 {
635 }
636 
637 /*ARGSUSED*/
638 void
639 apic_unset_idlecpu(processorid_t cpun)
640 {
641 }
642 
643 
644 void
645 apic_ret()
646 {
647 }
648 
649 /*
650  * If apic_coarse_time == 1, then apic_gettime() is used instead of
651  * apic_gethrtime().  This is used for performance instead of accuracy.
652  */
653 
654 hrtime_t
655 apic_gettime()
656 {
657 	int old_hrtime_stamp;
658 	hrtime_t temp;
659 
660 	/*
661 	 * In one-shot mode, we do not keep time, so if anyone
662 	 * calls psm_gettime() directly, we vector over to
663 	 * gethrtime().
664 	 * one-shot mode MUST NOT be enabled if this psm is the source of
665 	 * hrtime.
666 	 */
667 
668 	if (apic_oneshot)
669 		return (gethrtime());
670 
671 
672 gettime_again:
673 	while ((old_hrtime_stamp = apic_hrtime_stamp) & 1)
674 		apic_ret();
675 
676 	temp = apic_nsec_since_boot;
677 
678 	if (apic_hrtime_stamp != old_hrtime_stamp) {	/* got an interrupt */
679 		goto gettime_again;
680 	}
681 	return (temp);
682 }
683 
684 /*
685  * Here we return the number of nanoseconds since booting.  Note every
686  * clock interrupt increments apic_nsec_since_boot by the appropriate
687  * amount.
688  */
689 hrtime_t
690 apic_gethrtime(void)
691 {
692 	int curr_timeval, countval, elapsed_ticks;
693 	int old_hrtime_stamp, status;
694 	hrtime_t temp;
695 	uint32_t cpun;
696 	ulong_t oflags;
697 
698 	/*
699 	 * In one-shot mode, we do not keep time, so if anyone
700 	 * calls psm_gethrtime() directly, we vector over to
701 	 * gethrtime().
702 	 * one-shot mode MUST NOT be enabled if this psm is the source of
703 	 * hrtime.
704 	 */
705 
706 	if (apic_oneshot)
707 		return (gethrtime());
708 
709 	oflags = intr_clear();	/* prevent migration */
710 
711 	cpun = apic_reg_ops->apic_read(APIC_LID_REG);
712 	if (apic_mode == LOCAL_APIC)
713 		cpun >>= APIC_ID_BIT_OFFSET;
714 
715 	lock_set(&apic_gethrtime_lock);
716 
717 gethrtime_again:
718 	while ((old_hrtime_stamp = apic_hrtime_stamp) & 1)
719 		apic_ret();
720 
721 	/*
722 	 * Check to see which CPU we are on.  Note the time is kept on
723 	 * the local APIC of CPU 0.  If on CPU 0, simply read the current
724 	 * counter.  If on another CPU, issue a remote read command to CPU 0.
725 	 */
726 	if (cpun == apic_cpus[0].aci_local_id) {
727 		countval = apic_reg_ops->apic_read(APIC_CURR_COUNT);
728 	} else {
729 #ifdef	DEBUG
730 		APIC_AV_PENDING_SET();
731 #else
732 		if (apic_mode == LOCAL_APIC)
733 			APIC_AV_PENDING_SET();
734 #endif /* DEBUG */
735 
736 		apic_reg_ops->apic_write_int_cmd(
737 		    apic_cpus[0].aci_local_id, APIC_CURR_ADD | AV_REMOTE);
738 
739 		while ((status = apic_reg_ops->apic_read(APIC_INT_CMD1))
740 		    & AV_READ_PENDING) {
741 			apic_ret();
742 		}
743 
744 		if (status & AV_REMOTE_STATUS)	/* 1 = valid */
745 			countval = apic_reg_ops->apic_read(APIC_REMOTE_READ);
746 		else {	/* 0 = invalid */
747 			apic_remote_hrterr++;
748 			/*
749 			 * return last hrtime right now, will need more
750 			 * testing if change to retry
751 			 */
752 			temp = apic_last_hrtime;
753 
754 			lock_clear(&apic_gethrtime_lock);
755 
756 			intr_restore(oflags);
757 
758 			return (temp);
759 		}
760 	}
761 	if (countval > last_count_read)
762 		countval = 0;
763 	else
764 		last_count_read = countval;
765 
766 	elapsed_ticks = apic_hertz_count - countval;
767 
768 	curr_timeval = APIC_TICKS_TO_NSECS(elapsed_ticks);
769 	temp = apic_nsec_since_boot + curr_timeval;
770 
771 	if (apic_hrtime_stamp != old_hrtime_stamp) {	/* got an interrupt */
772 		/* we might have clobbered last_count_read. Restore it */
773 		last_count_read = apic_hertz_count;
774 		goto gethrtime_again;
775 	}
776 
777 	if (temp < apic_last_hrtime) {
778 		/* return last hrtime if error occurs */
779 		apic_hrtime_error++;
780 		temp = apic_last_hrtime;
781 	}
782 	else
783 		apic_last_hrtime = temp;
784 
785 	lock_clear(&apic_gethrtime_lock);
786 	intr_restore(oflags);
787 
788 	return (temp);
789 }
790 
791 /* apic NMI handler */
792 /*ARGSUSED*/
793 void
794 apic_nmi_intr(caddr_t arg, struct regs *rp)
795 {
796 	if (apic_shutdown_processors) {
797 		apic_disable_local_apic();
798 		return;
799 	}
800 
801 	apic_error |= APIC_ERR_NMI;
802 
803 	if (!lock_try(&apic_nmi_lock))
804 		return;
805 	apic_num_nmis++;
806 
807 	if (apic_kmdb_on_nmi && psm_debugger()) {
808 		debug_enter("NMI received: entering kmdb\n");
809 	} else if (apic_panic_on_nmi) {
810 		/* Keep panic from entering kmdb. */
811 		nopanicdebug = 1;
812 		panic("NMI received\n");
813 	} else {
814 		/*
815 		 * prom_printf is the best shot we have of something which is
816 		 * problem free from high level/NMI type of interrupts
817 		 */
818 		prom_printf("NMI received\n");
819 	}
820 
821 	lock_clear(&apic_nmi_lock);
822 }
823 
824 processorid_t
825 apic_get_next_processorid(processorid_t cpu_id)
826 {
827 
828 	int i;
829 
830 	if (cpu_id == -1)
831 		return ((processorid_t)0);
832 
833 	for (i = cpu_id + 1; i < NCPU; i++) {
834 		if (apic_cpu_in_range(i))
835 			return (i);
836 	}
837 
838 	return ((processorid_t)-1);
839 }
840 
841 int
842 apic_cpu_add(psm_cpu_request_t *reqp)
843 {
844 	int i, rv = 0;
845 	ulong_t iflag;
846 	boolean_t first = B_TRUE;
847 	uchar_t localver;
848 	uint32_t localid, procid;
849 	processorid_t cpuid = (processorid_t)-1;
850 	mach_cpu_add_arg_t *ap;
851 
852 	ASSERT(reqp != NULL);
853 	reqp->req.cpu_add.cpuid = (processorid_t)-1;
854 
855 	/* Check whether CPU hotplug is supported. */
856 	if (!plat_dr_support_cpu() || apic_max_nproc == -1) {
857 		return (ENOTSUP);
858 	}
859 
860 	ap = (mach_cpu_add_arg_t *)reqp->req.cpu_add.argp;
861 	switch (ap->type) {
862 	case MACH_CPU_ARG_LOCAL_APIC:
863 		localid = ap->arg.apic.apic_id;
864 		procid = ap->arg.apic.proc_id;
865 		if (localid >= 255 || procid > 255) {
866 			cmn_err(CE_WARN,
867 			    "!apic: apicid(%u) or procid(%u) is invalid.",
868 			    localid, procid);
869 			return (EINVAL);
870 		}
871 		break;
872 
873 	case MACH_CPU_ARG_LOCAL_X2APIC:
874 		localid = ap->arg.apic.apic_id;
875 		procid = ap->arg.apic.proc_id;
876 		if (localid >= UINT32_MAX) {
877 			cmn_err(CE_WARN,
878 			    "!apic: x2apicid(%u) is invalid.", localid);
879 			return (EINVAL);
880 		} else if (localid >= 255 && apic_mode == LOCAL_APIC) {
881 			cmn_err(CE_WARN, "!apic: system is in APIC mode, "
882 			    "can't support x2APIC processor.");
883 			return (ENOTSUP);
884 		}
885 		break;
886 
887 	default:
888 		cmn_err(CE_WARN,
889 		    "!apic: unknown argument type %d to apic_cpu_add().",
890 		    ap->type);
891 		return (EINVAL);
892 	}
893 
894 	/* Use apic_ioapic_lock to sync with apic_get_next_bind_cpu. */
895 	iflag = intr_clear();
896 	lock_set(&apic_ioapic_lock);
897 
898 	/* Check whether local APIC id already exists. */
899 	for (i = 0; i < apic_nproc; i++) {
900 		if (!CPU_IN_SET(apic_cpumask, i))
901 			continue;
902 		if (apic_cpus[i].aci_local_id == localid) {
903 			lock_clear(&apic_ioapic_lock);
904 			intr_restore(iflag);
905 			cmn_err(CE_WARN,
906 			    "!apic: local apic id %u already exists.",
907 			    localid);
908 			return (EEXIST);
909 		} else if (apic_cpus[i].aci_processor_id == procid) {
910 			lock_clear(&apic_ioapic_lock);
911 			intr_restore(iflag);
912 			cmn_err(CE_WARN,
913 			    "!apic: processor id %u already exists.",
914 			    (int)procid);
915 			return (EEXIST);
916 		}
917 
918 		/*
919 		 * There's no local APIC version number available in MADT table,
920 		 * so assume that all CPUs are homogeneous and use local APIC
921 		 * version number of the first existing CPU.
922 		 */
923 		if (first) {
924 			first = B_FALSE;
925 			localver = apic_cpus[i].aci_local_ver;
926 		}
927 	}
928 	ASSERT(first == B_FALSE);
929 
930 	/*
931 	 * Try to assign the same cpuid if APIC id exists in the dirty cache.
932 	 */
933 	for (i = 0; i < apic_max_nproc; i++) {
934 		if (CPU_IN_SET(apic_cpumask, i)) {
935 			ASSERT((apic_cpus[i].aci_status & APIC_CPU_FREE) == 0);
936 			continue;
937 		}
938 		ASSERT(apic_cpus[i].aci_status & APIC_CPU_FREE);
939 		if ((apic_cpus[i].aci_status & APIC_CPU_DIRTY) &&
940 		    apic_cpus[i].aci_local_id == localid &&
941 		    apic_cpus[i].aci_processor_id == procid) {
942 			cpuid = i;
943 			break;
944 		}
945 	}
946 
947 	/* Avoid the dirty cache and allocate fresh slot if possible. */
948 	if (cpuid == (processorid_t)-1) {
949 		for (i = 0; i < apic_max_nproc; i++) {
950 			if ((apic_cpus[i].aci_status & APIC_CPU_FREE) &&
951 			    (apic_cpus[i].aci_status & APIC_CPU_DIRTY) == 0) {
952 				cpuid = i;
953 				break;
954 			}
955 		}
956 	}
957 
958 	/* Try to find any free slot as last resort. */
959 	if (cpuid == (processorid_t)-1) {
960 		for (i = 0; i < apic_max_nproc; i++) {
961 			if (apic_cpus[i].aci_status & APIC_CPU_FREE) {
962 				cpuid = i;
963 				break;
964 			}
965 		}
966 	}
967 
968 	if (cpuid == (processorid_t)-1) {
969 		lock_clear(&apic_ioapic_lock);
970 		intr_restore(iflag);
971 		cmn_err(CE_NOTE,
972 		    "!apic: failed to allocate cpu id for processor %u.",
973 		    procid);
974 		rv = EAGAIN;
975 	} else if (ACPI_FAILURE(acpica_map_cpu(cpuid, procid))) {
976 		lock_clear(&apic_ioapic_lock);
977 		intr_restore(iflag);
978 		cmn_err(CE_NOTE,
979 		    "!apic: failed to build mapping for processor %u.",
980 		    procid);
981 		rv = EBUSY;
982 	} else {
983 		ASSERT(cpuid >= 0 && cpuid < NCPU);
984 		ASSERT(cpuid < apic_max_nproc && cpuid < max_ncpus);
985 		bzero(&apic_cpus[cpuid], sizeof (apic_cpus[0]));
986 		apic_cpus[cpuid].aci_processor_id = procid;
987 		apic_cpus[cpuid].aci_local_id = localid;
988 		apic_cpus[cpuid].aci_local_ver = localver;
989 		CPUSET_ATOMIC_ADD(apic_cpumask, cpuid);
990 		if (cpuid >= apic_nproc) {
991 			apic_nproc = cpuid + 1;
992 		}
993 		lock_clear(&apic_ioapic_lock);
994 		intr_restore(iflag);
995 		reqp->req.cpu_add.cpuid = cpuid;
996 	}
997 
998 	return (rv);
999 }
1000 
1001 int
1002 apic_cpu_remove(psm_cpu_request_t *reqp)
1003 {
1004 	int i;
1005 	ulong_t iflag;
1006 	processorid_t cpuid;
1007 
1008 	/* Check whether CPU hotplug is supported. */
1009 	if (!plat_dr_support_cpu() || apic_max_nproc == -1) {
1010 		return (ENOTSUP);
1011 	}
1012 
1013 	cpuid = reqp->req.cpu_remove.cpuid;
1014 
1015 	/* Use apic_ioapic_lock to sync with apic_get_next_bind_cpu. */
1016 	iflag = intr_clear();
1017 	lock_set(&apic_ioapic_lock);
1018 
1019 	if (!apic_cpu_in_range(cpuid)) {
1020 		lock_clear(&apic_ioapic_lock);
1021 		intr_restore(iflag);
1022 		cmn_err(CE_WARN,
1023 		    "!apic: cpuid %d doesn't exist in apic_cpus array.",
1024 		    cpuid);
1025 		return (ENODEV);
1026 	}
1027 	ASSERT((apic_cpus[cpuid].aci_status & APIC_CPU_FREE) == 0);
1028 
1029 	if (ACPI_FAILURE(acpica_unmap_cpu(cpuid))) {
1030 		lock_clear(&apic_ioapic_lock);
1031 		intr_restore(iflag);
1032 		return (ENOENT);
1033 	}
1034 
1035 	if (cpuid == apic_nproc - 1) {
1036 		/*
1037 		 * We are removing the highest numbered cpuid so we need to
1038 		 * find the next highest cpuid as the new value for apic_nproc.
1039 		 */
1040 		for (i = apic_nproc; i > 0; i--) {
1041 			if (CPU_IN_SET(apic_cpumask, i - 1)) {
1042 				apic_nproc = i;
1043 				break;
1044 			}
1045 		}
1046 		/* at least one CPU left */
1047 		ASSERT(i > 0);
1048 	}
1049 	CPUSET_ATOMIC_DEL(apic_cpumask, cpuid);
1050 	/* mark slot as free and keep it in the dirty cache */
1051 	apic_cpus[cpuid].aci_status = APIC_CPU_FREE | APIC_CPU_DIRTY;
1052 
1053 	lock_clear(&apic_ioapic_lock);
1054 	intr_restore(iflag);
1055 
1056 	return (0);
1057 }
1058 
1059 /*
1060  * Return the number of APIC clock ticks elapsed for 8245 to decrement
1061  * (APIC_TIME_COUNT + pit_ticks_adj) ticks.
1062  */
1063 uint_t
1064 apic_calibrate(volatile uint32_t *addr, uint16_t *pit_ticks_adj)
1065 {
1066 	uint8_t		pit_tick_lo;
1067 	uint16_t	pit_tick, target_pit_tick;
1068 	uint32_t	start_apic_tick, end_apic_tick;
1069 	ulong_t		iflag;
1070 	uint32_t	reg;
1071 
1072 	reg = addr + APIC_CURR_COUNT - apicadr;
1073 
1074 	iflag = intr_clear();
1075 
1076 	do {
1077 		pit_tick_lo = inb(PITCTR0_PORT);
1078 		pit_tick = (inb(PITCTR0_PORT) << 8) | pit_tick_lo;
1079 	} while (pit_tick < APIC_TIME_MIN ||
1080 	    pit_tick_lo <= APIC_LB_MIN || pit_tick_lo >= APIC_LB_MAX);
1081 
1082 	/*
1083 	 * Wait for the 8254 to decrement by 5 ticks to ensure
1084 	 * we didn't start in the middle of a tick.
1085 	 * Compare with 0x10 for the wrap around case.
1086 	 */
1087 	target_pit_tick = pit_tick - 5;
1088 	do {
1089 		pit_tick_lo = inb(PITCTR0_PORT);
1090 		pit_tick = (inb(PITCTR0_PORT) << 8) | pit_tick_lo;
1091 	} while (pit_tick > target_pit_tick || pit_tick_lo < 0x10);
1092 
1093 	start_apic_tick = apic_reg_ops->apic_read(reg);
1094 
1095 	/*
1096 	 * Wait for the 8254 to decrement by
1097 	 * (APIC_TIME_COUNT + pit_ticks_adj) ticks
1098 	 */
1099 	target_pit_tick = pit_tick - APIC_TIME_COUNT;
1100 	do {
1101 		pit_tick_lo = inb(PITCTR0_PORT);
1102 		pit_tick = (inb(PITCTR0_PORT) << 8) | pit_tick_lo;
1103 	} while (pit_tick > target_pit_tick || pit_tick_lo < 0x10);
1104 
1105 	end_apic_tick = apic_reg_ops->apic_read(reg);
1106 
1107 	*pit_ticks_adj = target_pit_tick - pit_tick;
1108 
1109 	intr_restore(iflag);
1110 
1111 	return (start_apic_tick - end_apic_tick);
1112 }
1113 
1114 /*
1115  * Initialise the APIC timer on the local APIC of CPU 0 to the desired
1116  * frequency.  Note at this stage in the boot sequence, the boot processor
1117  * is the only active processor.
1118  * hertz value of 0 indicates a one-shot mode request.  In this case
1119  * the function returns the resolution (in nanoseconds) for the hardware
1120  * timer interrupt.  If one-shot mode capability is not available,
1121  * the return value will be 0. apic_enable_oneshot is a global switch
1122  * for disabling the functionality.
1123  * A non-zero positive value for hertz indicates a periodic mode request.
1124  * In this case the hardware will be programmed to generate clock interrupts
1125  * at hertz frequency and returns the resolution of interrupts in
1126  * nanosecond.
1127  */
1128 
1129 int
1130 apic_clkinit(int hertz)
1131 {
1132 	int		ret;
1133 
1134 	apic_int_busy_mark = (apic_int_busy_mark *
1135 	    apic_sample_factor_redistribution) / 100;
1136 	apic_int_free_mark = (apic_int_free_mark *
1137 	    apic_sample_factor_redistribution) / 100;
1138 	apic_diff_for_redistribution = (apic_diff_for_redistribution *
1139 	    apic_sample_factor_redistribution) / 100;
1140 
1141 	ret = apic_timer_init(hertz);
1142 	return (ret);
1143 
1144 }
1145 
1146 /*
1147  * apic_preshutdown:
1148  * Called early in shutdown whilst we can still access filesystems to do
1149  * things like loading modules which will be required to complete shutdown
1150  * after filesystems are all unmounted.
1151  */
1152 void
1153 apic_preshutdown(int cmd, int fcn)
1154 {
1155 	APIC_VERBOSE_POWEROFF(("apic_preshutdown(%d,%d); m=%d a=%d\n",
1156 	    cmd, fcn, apic_poweroff_method, apic_enable_acpi));
1157 }
1158 
1159 void
1160 apic_shutdown(int cmd, int fcn)
1161 {
1162 	int restarts, attempts;
1163 	int i;
1164 	uchar_t	byte;
1165 	ulong_t iflag;
1166 
1167 	hpet_acpi_fini();
1168 
1169 	/* Send NMI to all CPUs except self to do per processor shutdown */
1170 	iflag = intr_clear();
1171 #ifdef	DEBUG
1172 	APIC_AV_PENDING_SET();
1173 #else
1174 	if (apic_mode == LOCAL_APIC)
1175 		APIC_AV_PENDING_SET();
1176 #endif /* DEBUG */
1177 	apic_shutdown_processors = 1;
1178 	apic_reg_ops->apic_write(APIC_INT_CMD1,
1179 	    AV_NMI | AV_LEVEL | AV_SH_ALL_EXCSELF);
1180 
1181 	/* restore cmos shutdown byte before reboot */
1182 	if (apic_cmos_ssb_set) {
1183 		outb(CMOS_ADDR, SSB);
1184 		outb(CMOS_DATA, 0);
1185 	}
1186 
1187 	ioapic_disable_redirection();
1188 
1189 	/*	disable apic mode if imcr present	*/
1190 	if (apic_imcrp) {
1191 		outb(APIC_IMCR_P1, (uchar_t)APIC_IMCR_SELECT);
1192 		outb(APIC_IMCR_P2, (uchar_t)APIC_IMCR_PIC);
1193 	}
1194 
1195 	apic_disable_local_apic();
1196 
1197 	intr_restore(iflag);
1198 
1199 	/* remainder of function is for shutdown cases only */
1200 	if (cmd != A_SHUTDOWN)
1201 		return;
1202 
1203 	/*
1204 	 * Switch system back into Legacy-Mode if using ACPI and
1205 	 * not powering-off.  Some BIOSes need to remain in ACPI-mode
1206 	 * for power-off to succeed (Dell Dimension 4600)
1207 	 * Do not disable ACPI while doing fastreboot
1208 	 */
1209 	if (apic_enable_acpi && fcn != AD_POWEROFF && fcn != AD_FASTREBOOT)
1210 		(void) AcpiDisable();
1211 
1212 	if (fcn == AD_FASTREBOOT) {
1213 		apic_reg_ops->apic_write(APIC_INT_CMD1,
1214 		    AV_ASSERT | AV_RESET | AV_SH_ALL_EXCSELF);
1215 	}
1216 
1217 	/* remainder of function is for shutdown+poweroff case only */
1218 	if (fcn != AD_POWEROFF)
1219 		return;
1220 
1221 	switch (apic_poweroff_method) {
1222 		case APIC_POWEROFF_VIA_RTC:
1223 
1224 			/* select the extended NVRAM bank in the RTC */
1225 			outb(CMOS_ADDR, RTC_REGA);
1226 			byte = inb(CMOS_DATA);
1227 			outb(CMOS_DATA, (byte | EXT_BANK));
1228 
1229 			outb(CMOS_ADDR, PFR_REG);
1230 
1231 			/* for Predator must toggle the PAB bit */
1232 			byte = inb(CMOS_DATA);
1233 
1234 			/*
1235 			 * clear power active bar, wakeup alarm and
1236 			 * kickstart
1237 			 */
1238 			byte &= ~(PAB_CBIT | WF_FLAG | KS_FLAG);
1239 			outb(CMOS_DATA, byte);
1240 
1241 			/* delay before next write */
1242 			drv_usecwait(1000);
1243 
1244 			/* for S40 the following would suffice */
1245 			byte = inb(CMOS_DATA);
1246 
1247 			/* power active bar control bit */
1248 			byte |= PAB_CBIT;
1249 			outb(CMOS_DATA, byte);
1250 
1251 			break;
1252 
1253 		case APIC_POWEROFF_VIA_ASPEN_BMC:
1254 			restarts = 0;
1255 restart_aspen_bmc:
1256 			if (++restarts == 3)
1257 				break;
1258 			attempts = 0;
1259 			do {
1260 				byte = inb(MISMIC_FLAG_REGISTER);
1261 				byte &= MISMIC_BUSY_MASK;
1262 				if (byte != 0) {
1263 					drv_usecwait(1000);
1264 					if (attempts >= 3)
1265 						goto restart_aspen_bmc;
1266 					++attempts;
1267 				}
1268 			} while (byte != 0);
1269 			outb(MISMIC_CNTL_REGISTER, CC_SMS_GET_STATUS);
1270 			byte = inb(MISMIC_FLAG_REGISTER);
1271 			byte |= 0x1;
1272 			outb(MISMIC_FLAG_REGISTER, byte);
1273 			i = 0;
1274 			for (; i < (sizeof (aspen_bmc)/sizeof (aspen_bmc[0]));
1275 			    i++) {
1276 				attempts = 0;
1277 				do {
1278 					byte = inb(MISMIC_FLAG_REGISTER);
1279 					byte &= MISMIC_BUSY_MASK;
1280 					if (byte != 0) {
1281 						drv_usecwait(1000);
1282 						if (attempts >= 3)
1283 							goto restart_aspen_bmc;
1284 						++attempts;
1285 					}
1286 				} while (byte != 0);
1287 				outb(MISMIC_CNTL_REGISTER, aspen_bmc[i].cntl);
1288 				outb(MISMIC_DATA_REGISTER, aspen_bmc[i].data);
1289 				byte = inb(MISMIC_FLAG_REGISTER);
1290 				byte |= 0x1;
1291 				outb(MISMIC_FLAG_REGISTER, byte);
1292 			}
1293 			break;
1294 
1295 		case APIC_POWEROFF_VIA_SITKA_BMC:
1296 			restarts = 0;
1297 restart_sitka_bmc:
1298 			if (++restarts == 3)
1299 				break;
1300 			attempts = 0;
1301 			do {
1302 				byte = inb(SMS_STATUS_REGISTER);
1303 				byte &= SMS_STATE_MASK;
1304 				if ((byte == SMS_READ_STATE) ||
1305 				    (byte == SMS_WRITE_STATE)) {
1306 					drv_usecwait(1000);
1307 					if (attempts >= 3)
1308 						goto restart_sitka_bmc;
1309 					++attempts;
1310 				}
1311 			} while ((byte == SMS_READ_STATE) ||
1312 			    (byte == SMS_WRITE_STATE));
1313 			outb(SMS_COMMAND_REGISTER, SMS_GET_STATUS);
1314 			i = 0;
1315 			for (; i < (sizeof (sitka_bmc)/sizeof (sitka_bmc[0]));
1316 			    i++) {
1317 				attempts = 0;
1318 				do {
1319 					byte = inb(SMS_STATUS_REGISTER);
1320 					byte &= SMS_IBF_MASK;
1321 					if (byte != 0) {
1322 						drv_usecwait(1000);
1323 						if (attempts >= 3)
1324 							goto restart_sitka_bmc;
1325 						++attempts;
1326 					}
1327 				} while (byte != 0);
1328 				outb(sitka_bmc[i].port, sitka_bmc[i].data);
1329 			}
1330 			break;
1331 
1332 		case APIC_POWEROFF_NONE:
1333 
1334 			/* If no APIC direct method, we will try using ACPI */
1335 			if (apic_enable_acpi) {
1336 				if (acpi_poweroff() == 1)
1337 					return;
1338 			} else
1339 				return;
1340 
1341 			break;
1342 	}
1343 	/*
1344 	 * Wait a limited time here for power to go off.
1345 	 * If the power does not go off, then there was a
1346 	 * problem and we should continue to the halt which
1347 	 * prints a message for the user to press a key to
1348 	 * reboot.
1349 	 */
1350 	drv_usecwait(7000000); /* wait seven seconds */
1351 
1352 }
1353 
1354 ddi_periodic_t apic_periodic_id;
1355 
1356 /*
1357  * The following functions are in the platform specific file so that they
1358  * can be different functions depending on whether we are running on
1359  * bare metal or a hypervisor.
1360  */
1361 
1362 /*
1363  * map an apic for memory-mapped access
1364  */
1365 uint32_t *
1366 mapin_apic(uint32_t addr, size_t len, int flags)
1367 {
1368 	return ((void *)psm_map_phys(addr, len, flags));
1369 }
1370 
1371 uint32_t *
1372 mapin_ioapic(uint32_t addr, size_t len, int flags)
1373 {
1374 	return (mapin_apic(addr, len, flags));
1375 }
1376 
1377 /*
1378  * unmap an apic
1379  */
1380 void
1381 mapout_apic(caddr_t addr, size_t len)
1382 {
1383 	psm_unmap_phys(addr, len);
1384 }
1385 
1386 void
1387 mapout_ioapic(caddr_t addr, size_t len)
1388 {
1389 	mapout_apic(addr, len);
1390 }
1391 
1392 uint32_t
1393 ioapic_read(int ioapic_ix, uint32_t reg)
1394 {
1395 	volatile uint32_t *ioapic;
1396 
1397 	ioapic = apicioadr[ioapic_ix];
1398 	ioapic[APIC_IO_REG] = reg;
1399 	return (ioapic[APIC_IO_DATA]);
1400 }
1401 
1402 void
1403 ioapic_write(int ioapic_ix, uint32_t reg, uint32_t value)
1404 {
1405 	volatile uint32_t *ioapic;
1406 
1407 	ioapic = apicioadr[ioapic_ix];
1408 	ioapic[APIC_IO_REG] = reg;
1409 	ioapic[APIC_IO_DATA] = value;
1410 }
1411 
1412 void
1413 ioapic_write_eoi(int ioapic_ix, uint32_t value)
1414 {
1415 	volatile uint32_t *ioapic;
1416 
1417 	ioapic = apicioadr[ioapic_ix];
1418 	ioapic[APIC_IO_EOI] = value;
1419 }
1420 
1421 /*
1422  * Round-robin algorithm to find the next CPU with interrupts enabled.
1423  * It can't share the same static variable apic_next_bind_cpu with
1424  * apic_get_next_bind_cpu(), since that will cause all interrupts to be
1425  * bound to CPU1 at boot time.  During boot, only CPU0 is online with
1426  * interrupts enabled when apic_get_next_bind_cpu() and apic_find_cpu()
1427  * are called.  However, the pcplusmp driver assumes that there will be
1428  * boot_ncpus CPUs configured eventually so it tries to distribute all
1429  * interrupts among CPU0 - CPU[boot_ncpus - 1].  Thus to prevent all
1430  * interrupts being targetted at CPU1, we need to use a dedicated static
1431  * variable for find_next_cpu() instead of sharing apic_next_bind_cpu.
1432  */
1433 
1434 processorid_t
1435 apic_find_cpu(int flag)
1436 {
1437 	int i;
1438 	static processorid_t acid = 0;
1439 
1440 	/* Find the first CPU with the passed-in flag set */
1441 	for (i = 0; i < apic_nproc; i++) {
1442 		if (++acid >= apic_nproc) {
1443 			acid = 0;
1444 		}
1445 		if (apic_cpu_in_range(acid) &&
1446 		    (apic_cpus[acid].aci_status & flag)) {
1447 			break;
1448 		}
1449 	}
1450 
1451 	ASSERT((apic_cpus[acid].aci_status & flag) != 0);
1452 	return (acid);
1453 }
1454 
1455 /*
1456  * Switch between safe and x2APIC IPI sending method.
1457  * CPU may power on in xapic mode or x2apic mode. If CPU needs to send IPI to
1458  * other CPUs before entering x2APIC mode, it still needs to xAPIC method.
1459  * Before sending StartIPI to target CPU, psm_send_ipi will be changed to
1460  * apic_common_send_ipi, which detects current local APIC mode and use right
1461  * method to send IPI. If some CPUs fail to start up, apic_poweron_cnt
1462  * won't return to zero, so apic_common_send_ipi will always be used.
1463  * psm_send_ipi can't be simply changed back to x2apic_send_ipi if some CPUs
1464  * failed to start up because those failed CPUs may recover itself later at
1465  * unpredictable time.
1466  */
1467 void
1468 apic_switch_ipi_callback(boolean_t enter)
1469 {
1470 	ulong_t iflag;
1471 	struct psm_ops *pops = psmops;
1472 
1473 	iflag = intr_clear();
1474 	lock_set(&apic_mode_switch_lock);
1475 	if (enter) {
1476 		ASSERT(apic_poweron_cnt >= 0);
1477 		if (apic_poweron_cnt == 0) {
1478 			pops->psm_send_ipi = apic_common_send_ipi;
1479 			send_dirintf = pops->psm_send_ipi;
1480 		}
1481 		apic_poweron_cnt++;
1482 	} else {
1483 		ASSERT(apic_poweron_cnt > 0);
1484 		apic_poweron_cnt--;
1485 		if (apic_poweron_cnt == 0) {
1486 			pops->psm_send_ipi = x2apic_send_ipi;
1487 			send_dirintf = pops->psm_send_ipi;
1488 		}
1489 	}
1490 	lock_clear(&apic_mode_switch_lock);
1491 	intr_restore(iflag);
1492 }
1493 
1494 void
1495 apic_intrmap_init(int apic_mode)
1496 {
1497 	int suppress_brdcst_eoi = 0;
1498 
1499 	if (psm_vt_ops != NULL) {
1500 		/*
1501 		 * Since X2APIC requires the use of interrupt remapping
1502 		 * (though this is not documented explicitly in the Intel
1503 		 * documentation (yet)), initialize interrupt remapping
1504 		 * support before initializing the X2APIC unit.
1505 		 */
1506 		if (((apic_intrmap_ops_t *)psm_vt_ops)->
1507 		    apic_intrmap_init(apic_mode) == DDI_SUCCESS) {
1508 
1509 			apic_vt_ops = psm_vt_ops;
1510 
1511 			/*
1512 			 * We leverage the interrupt remapping engine to
1513 			 * suppress broadcast EOI; thus we must send the
1514 			 * directed EOI with the directed-EOI handler.
1515 			 */
1516 			if (apic_directed_EOI_supported() == 0) {
1517 				suppress_brdcst_eoi = 1;
1518 			}
1519 
1520 			apic_vt_ops->apic_intrmap_enable(suppress_brdcst_eoi);
1521 
1522 			if (apic_detect_x2apic()) {
1523 				apic_enable_x2apic();
1524 			}
1525 
1526 			if (apic_directed_EOI_supported() == 0) {
1527 				apic_set_directed_EOI_handler();
1528 			}
1529 		}
1530 	}
1531 }
1532 
1533 /*ARGSUSED*/
1534 static void
1535 apic_record_ioapic_rdt(void *intrmap_private, ioapic_rdt_t *irdt)
1536 {
1537 	irdt->ir_hi <<= APIC_ID_BIT_OFFSET;
1538 }
1539 
1540 /*ARGSUSED*/
1541 static void
1542 apic_record_msi(void *intrmap_private, msi_regs_t *mregs)
1543 {
1544 	mregs->mr_addr = MSI_ADDR_HDR |
1545 	    (MSI_ADDR_RH_FIXED << MSI_ADDR_RH_SHIFT) |
1546 	    (MSI_ADDR_DM_PHYSICAL << MSI_ADDR_DM_SHIFT) |
1547 	    (mregs->mr_addr << MSI_ADDR_DEST_SHIFT);
1548 	mregs->mr_data = (MSI_DATA_TM_EDGE << MSI_DATA_TM_SHIFT) |
1549 	    mregs->mr_data;
1550 }
1551 
1552 /*
1553  * Functions from apic_introp.c
1554  *
1555  * Those functions are used by apic_intr_ops().
1556  */
1557 
1558 /*
1559  * MSI support flag:
1560  * reflects whether MSI is supported at APIC level
1561  * it can also be patched through /etc/system
1562  *
1563  *  0 = default value - don't know and need to call apic_check_msi_support()
1564  *      to find out then set it accordingly
1565  *  1 = supported
1566  * -1 = not supported
1567  */
1568 int	apic_support_msi = 0;
1569 
1570 /* Multiple vector support for MSI-X */
1571 int	apic_msix_enable = 1;
1572 
1573 /* Multiple vector support for MSI */
1574 int	apic_multi_msi_enable = 1;
1575 
1576 /*
1577  * check whether the system supports MSI
1578  *
1579  * If PCI-E capability is found, then this must be a PCI-E system.
1580  * Since MSI is required for PCI-E system, it returns PSM_SUCCESS
1581  * to indicate this system supports MSI.
1582  */
1583 int
1584 apic_check_msi_support()
1585 {
1586 	dev_info_t *cdip;
1587 	char dev_type[16];
1588 	int dev_len;
1589 
1590 	DDI_INTR_IMPLDBG((CE_CONT, "apic_check_msi_support:\n"));
1591 
1592 	/*
1593 	 * check whether the first level children of root_node have
1594 	 * PCI-E capability
1595 	 */
1596 	for (cdip = ddi_get_child(ddi_root_node()); cdip != NULL;
1597 	    cdip = ddi_get_next_sibling(cdip)) {
1598 
1599 		DDI_INTR_IMPLDBG((CE_CONT, "apic_check_msi_support: cdip: 0x%p,"
1600 		    " driver: %s, binding: %s, nodename: %s\n", (void *)cdip,
1601 		    ddi_driver_name(cdip), ddi_binding_name(cdip),
1602 		    ddi_node_name(cdip)));
1603 		dev_len = sizeof (dev_type);
1604 		if (ddi_getlongprop_buf(DDI_DEV_T_ANY, cdip, DDI_PROP_DONTPASS,
1605 		    "device_type", (caddr_t)dev_type, &dev_len)
1606 		    != DDI_PROP_SUCCESS)
1607 			continue;
1608 		if (strcmp(dev_type, "pciex") == 0)
1609 			return (PSM_SUCCESS);
1610 	}
1611 
1612 	/* MSI is not supported on this system */
1613 	DDI_INTR_IMPLDBG((CE_CONT, "apic_check_msi_support: no 'pciex' "
1614 	    "device_type found\n"));
1615 	return (PSM_FAILURE);
1616 }
1617 
1618 /*
1619  * apic_pci_msi_unconfigure:
1620  *
1621  * This and next two interfaces are copied from pci_intr_lib.c
1622  * Do ensure that these two files stay in sync.
1623  * These needed to be copied over here to avoid a deadlock situation on
1624  * certain mp systems that use MSI interrupts.
1625  *
1626  * IMPORTANT regards next three interfaces:
1627  * i) are called only for MSI/X interrupts.
1628  * ii) called with interrupts disabled, and must not block
1629  */
1630 void
1631 apic_pci_msi_unconfigure(dev_info_t *rdip, int type, int inum)
1632 {
1633 	ushort_t		msi_ctrl;
1634 	int			cap_ptr = i_ddi_get_msi_msix_cap_ptr(rdip);
1635 	ddi_acc_handle_t	handle = i_ddi_get_pci_config_handle(rdip);
1636 
1637 	ASSERT((handle != NULL) && (cap_ptr != 0));
1638 
1639 	if (type == DDI_INTR_TYPE_MSI) {
1640 		msi_ctrl = pci_config_get16(handle, cap_ptr + PCI_MSI_CTRL);
1641 		msi_ctrl &= (~PCI_MSI_MME_MASK);
1642 		pci_config_put16(handle, cap_ptr + PCI_MSI_CTRL, msi_ctrl);
1643 		pci_config_put32(handle, cap_ptr + PCI_MSI_ADDR_OFFSET, 0);
1644 
1645 		if (msi_ctrl &  PCI_MSI_64BIT_MASK) {
1646 			pci_config_put16(handle,
1647 			    cap_ptr + PCI_MSI_64BIT_DATA, 0);
1648 			pci_config_put32(handle,
1649 			    cap_ptr + PCI_MSI_ADDR_OFFSET + 4, 0);
1650 		} else {
1651 			pci_config_put16(handle,
1652 			    cap_ptr + PCI_MSI_32BIT_DATA, 0);
1653 		}
1654 
1655 	} else if (type == DDI_INTR_TYPE_MSIX) {
1656 		uintptr_t	off;
1657 		uint32_t	mask;
1658 		ddi_intr_msix_t	*msix_p = i_ddi_get_msix(rdip);
1659 
1660 		ASSERT(msix_p != NULL);
1661 
1662 		/* Offset into "inum"th entry in the MSI-X table & mask it */
1663 		off = (uintptr_t)msix_p->msix_tbl_addr + (inum *
1664 		    PCI_MSIX_VECTOR_SIZE) + PCI_MSIX_VECTOR_CTRL_OFFSET;
1665 
1666 		mask = ddi_get32(msix_p->msix_tbl_hdl, (uint32_t *)off);
1667 
1668 		ddi_put32(msix_p->msix_tbl_hdl, (uint32_t *)off, (mask | 1));
1669 
1670 		/* Offset into the "inum"th entry in the MSI-X table */
1671 		off = (uintptr_t)msix_p->msix_tbl_addr +
1672 		    (inum * PCI_MSIX_VECTOR_SIZE);
1673 
1674 		/* Reset the "data" and "addr" bits */
1675 		ddi_put32(msix_p->msix_tbl_hdl,
1676 		    (uint32_t *)(off + PCI_MSIX_DATA_OFFSET), 0);
1677 		ddi_put64(msix_p->msix_tbl_hdl, (uint64_t *)off, 0);
1678 	}
1679 }
1680 
1681 /*
1682  * apic_pci_msi_disable_mode:
1683  */
1684 void
1685 apic_pci_msi_disable_mode(dev_info_t *rdip, int type)
1686 {
1687 	ushort_t		msi_ctrl;
1688 	int			cap_ptr = i_ddi_get_msi_msix_cap_ptr(rdip);
1689 	ddi_acc_handle_t	handle = i_ddi_get_pci_config_handle(rdip);
1690 
1691 	ASSERT((handle != NULL) && (cap_ptr != 0));
1692 
1693 	if (type == DDI_INTR_TYPE_MSI) {
1694 		msi_ctrl = pci_config_get16(handle, cap_ptr + PCI_MSI_CTRL);
1695 		if (!(msi_ctrl & PCI_MSI_ENABLE_BIT))
1696 			return;
1697 
1698 		msi_ctrl &= ~PCI_MSI_ENABLE_BIT;	/* MSI disable */
1699 		pci_config_put16(handle, cap_ptr + PCI_MSI_CTRL, msi_ctrl);
1700 
1701 	} else if (type == DDI_INTR_TYPE_MSIX) {
1702 		msi_ctrl = pci_config_get16(handle, cap_ptr + PCI_MSIX_CTRL);
1703 		if (msi_ctrl & PCI_MSIX_ENABLE_BIT) {
1704 			msi_ctrl &= ~PCI_MSIX_ENABLE_BIT;
1705 			pci_config_put16(handle, cap_ptr + PCI_MSIX_CTRL,
1706 			    msi_ctrl);
1707 		}
1708 	}
1709 }
1710 
1711 uint32_t
1712 apic_get_localapicid(uint32_t cpuid)
1713 {
1714 	ASSERT(cpuid < apic_nproc && apic_cpus != NULL);
1715 
1716 	return (apic_cpus[cpuid].aci_local_id);
1717 }
1718 
1719 uchar_t
1720 apic_get_ioapicid(uchar_t ioapicindex)
1721 {
1722 	ASSERT(ioapicindex < MAX_IO_APIC);
1723 
1724 	return (apic_io_id[ioapicindex]);
1725 }
1726