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 * Copyright (c) 2013, Joyent, Inc. All rights reserved.
27 * Copyright (c) 2016 by Delphix. All rights reserved.
28 */
29
30 /*
31 * PSMI 1.1 extensions are supported only in 2.6 and later versions.
32 * PSMI 1.2 extensions are supported only in 2.7 and later versions.
33 * PSMI 1.3 and 1.4 extensions are supported in Solaris 10.
34 * PSMI 1.5 extensions are supported in Solaris Nevada.
35 * PSMI 1.6 extensions are supported in Solaris Nevada.
36 * PSMI 1.7 extensions are supported in Solaris Nevada.
37 */
38 #define PSMI_1_7
39
40 #include <sys/processor.h>
41 #include <sys/time.h>
42 #include <sys/psm.h>
43 #include <sys/smp_impldefs.h>
44 #include <sys/cram.h>
45 #include <sys/acpi/acpi.h>
46 #include <sys/acpica.h>
111 int apic_setspl_delay = 1; /* apic_setspl - delay enable */
112 int apic_clkvect;
113
114 /* vector at which error interrupts come in */
115 int apic_errvect;
116 int apic_enable_error_intr = 1;
117 int apic_error_display_delay = 100;
118
119 /* vector at which performance counter overflow interrupts come in */
120 int apic_cpcovf_vect;
121 int apic_enable_cpcovf_intr = 1;
122
123 /* vector at which CMCI interrupts come in */
124 int apic_cmci_vect;
125 extern int cmi_enable_cmci;
126 extern void cmi_cmci_trap(void);
127
128 kmutex_t cmci_cpu_setup_lock; /* protects cmci_cpu_setup_registered */
129 int cmci_cpu_setup_registered;
130
131 /* number of CPUs in power-on transition state */
132 static int apic_poweron_cnt = 0;
133 lock_t apic_mode_switch_lock;
134
135 /*
136 * Patchable global variables.
137 */
138 int apic_forceload = 0;
139
140 int apic_coarse_hrtime = 1; /* 0 - use accurate slow gethrtime() */
141
142 int apic_flat_model = 0; /* 0 - clustered. 1 - flat */
143 int apic_panic_on_nmi = 0;
144 int apic_panic_on_apic_error = 0;
145
146 int apic_verbose = 0; /* 0x1ff */
147
148 #ifdef DEBUG
149 int apic_debug = 0;
150 int apic_restrict_vector = 0;
151
152 int apic_debug_msgbuf[APIC_DEBUG_MSGBUFSIZE];
1439 apic_find_cpu(int flag)
1440 {
1441 int i;
1442 static processorid_t acid = 0;
1443
1444 /* Find the first CPU with the passed-in flag set */
1445 for (i = 0; i < apic_nproc; i++) {
1446 if (++acid >= apic_nproc) {
1447 acid = 0;
1448 }
1449 if (apic_cpu_in_range(acid) &&
1450 (apic_cpus[acid].aci_status & flag)) {
1451 break;
1452 }
1453 }
1454
1455 ASSERT((apic_cpus[acid].aci_status & flag) != 0);
1456 return (acid);
1457 }
1458
1459 /*
1460 * Switch between safe and x2APIC IPI sending method.
1461 * CPU may power on in xapic mode or x2apic mode. If CPU needs to send IPI to
1462 * other CPUs before entering x2APIC mode, it still needs to xAPIC method.
1463 * Before sending StartIPI to target CPU, psm_send_ipi will be changed to
1464 * apic_common_send_ipi, which detects current local APIC mode and use right
1465 * method to send IPI. If some CPUs fail to start up, apic_poweron_cnt
1466 * won't return to zero, so apic_common_send_ipi will always be used.
1467 * psm_send_ipi can't be simply changed back to x2apic_send_ipi if some CPUs
1468 * failed to start up because those failed CPUs may recover itself later at
1469 * unpredictable time.
1470 */
1471 void
1472 apic_switch_ipi_callback(boolean_t enter)
1473 {
1474 ulong_t iflag;
1475 struct psm_ops *pops = psmops;
1476
1477 iflag = intr_clear();
1478 lock_set(&apic_mode_switch_lock);
1479 if (enter) {
1480 ASSERT(apic_poweron_cnt >= 0);
1481 if (apic_poweron_cnt == 0) {
1482 pops->psm_send_ipi = apic_common_send_ipi;
1483 send_dirintf = pops->psm_send_ipi;
1484 }
1485 apic_poweron_cnt++;
1486 } else {
1487 ASSERT(apic_poweron_cnt > 0);
1488 apic_poweron_cnt--;
1489 if (apic_poweron_cnt == 0) {
1490 pops->psm_send_ipi = x2apic_send_ipi;
1491 send_dirintf = pops->psm_send_ipi;
1492 }
1493 }
1494 lock_clear(&apic_mode_switch_lock);
1495 intr_restore(iflag);
1496 }
1497
1498 void
1499 apic_intrmap_init(int apic_mode)
1500 {
1501 int suppress_brdcst_eoi = 0;
1502
1503 /*
1504 * Intel Software Developer's Manual 3A, 10.12.7:
1505 *
1506 * Routing of device interrupts to local APIC units operating in
1507 * x2APIC mode requires use of the interrupt-remapping architecture
1508 * specified in the Intel Virtualization Technology for Directed
1509 * I/O, Revision 1.3. Because of this, BIOS must enumerate support
1510 * for and software must enable this interrupt remapping with
1511 * Extended Interrupt Mode Enabled before it enabling x2APIC mode in
1512 * the local APIC units.
1513 *
1514 *
1515 * In other words, to use the APIC in x2APIC mode, we need interrupt
1516 * remapping. Since we don't start up the IOMMU by default, we
1517 * won't be able to do any interrupt remapping and therefore have to
|
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 * Copyright (c) 2017, Joyent, Inc. All rights reserved.
27 * Copyright (c) 2016 by Delphix. All rights reserved.
28 */
29
30 /*
31 * PSMI 1.1 extensions are supported only in 2.6 and later versions.
32 * PSMI 1.2 extensions are supported only in 2.7 and later versions.
33 * PSMI 1.3 and 1.4 extensions are supported in Solaris 10.
34 * PSMI 1.5 extensions are supported in Solaris Nevada.
35 * PSMI 1.6 extensions are supported in Solaris Nevada.
36 * PSMI 1.7 extensions are supported in Solaris Nevada.
37 */
38 #define PSMI_1_7
39
40 #include <sys/processor.h>
41 #include <sys/time.h>
42 #include <sys/psm.h>
43 #include <sys/smp_impldefs.h>
44 #include <sys/cram.h>
45 #include <sys/acpi/acpi.h>
46 #include <sys/acpica.h>
111 int apic_setspl_delay = 1; /* apic_setspl - delay enable */
112 int apic_clkvect;
113
114 /* vector at which error interrupts come in */
115 int apic_errvect;
116 int apic_enable_error_intr = 1;
117 int apic_error_display_delay = 100;
118
119 /* vector at which performance counter overflow interrupts come in */
120 int apic_cpcovf_vect;
121 int apic_enable_cpcovf_intr = 1;
122
123 /* vector at which CMCI interrupts come in */
124 int apic_cmci_vect;
125 extern int cmi_enable_cmci;
126 extern void cmi_cmci_trap(void);
127
128 kmutex_t cmci_cpu_setup_lock; /* protects cmci_cpu_setup_registered */
129 int cmci_cpu_setup_registered;
130
131 lock_t apic_mode_switch_lock;
132
133 /*
134 * Patchable global variables.
135 */
136 int apic_forceload = 0;
137
138 int apic_coarse_hrtime = 1; /* 0 - use accurate slow gethrtime() */
139
140 int apic_flat_model = 0; /* 0 - clustered. 1 - flat */
141 int apic_panic_on_nmi = 0;
142 int apic_panic_on_apic_error = 0;
143
144 int apic_verbose = 0; /* 0x1ff */
145
146 #ifdef DEBUG
147 int apic_debug = 0;
148 int apic_restrict_vector = 0;
149
150 int apic_debug_msgbuf[APIC_DEBUG_MSGBUFSIZE];
1437 apic_find_cpu(int flag)
1438 {
1439 int i;
1440 static processorid_t acid = 0;
1441
1442 /* Find the first CPU with the passed-in flag set */
1443 for (i = 0; i < apic_nproc; i++) {
1444 if (++acid >= apic_nproc) {
1445 acid = 0;
1446 }
1447 if (apic_cpu_in_range(acid) &&
1448 (apic_cpus[acid].aci_status & flag)) {
1449 break;
1450 }
1451 }
1452
1453 ASSERT((apic_cpus[acid].aci_status & flag) != 0);
1454 return (acid);
1455 }
1456
1457 void
1458 apic_intrmap_init(int apic_mode)
1459 {
1460 int suppress_brdcst_eoi = 0;
1461
1462 /*
1463 * Intel Software Developer's Manual 3A, 10.12.7:
1464 *
1465 * Routing of device interrupts to local APIC units operating in
1466 * x2APIC mode requires use of the interrupt-remapping architecture
1467 * specified in the Intel Virtualization Technology for Directed
1468 * I/O, Revision 1.3. Because of this, BIOS must enumerate support
1469 * for and software must enable this interrupt remapping with
1470 * Extended Interrupt Mode Enabled before it enabling x2APIC mode in
1471 * the local APIC units.
1472 *
1473 *
1474 * In other words, to use the APIC in x2APIC mode, we need interrupt
1475 * remapping. Since we don't start up the IOMMU by default, we
1476 * won't be able to do any interrupt remapping and therefore have to
|