Print this page
8620 pcplusmp shouldn't support x2APIC mode
Reviewed by: Robert Mustacchi <rm@joyent.com>
Reviewed by: Jerry Jelinek <jerry.jelinek@joyent.com>


   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