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) 1993, 2010, Oracle and/or its affiliates. All rights reserved.
24 */
25 /*
26 * Copyright (c) 2010, Intel Corporation.
27 * All rights reserved.
28 */
29
30 /*
31 * To understand how the pcplusmp module interacts with the interrupt subsystem
32 * read the theory statement in uts/i86pc/os/intr.c.
33 */
34
35 /*
36 * PSMI 1.1 extensions are supported only in 2.6 and later versions.
37 * PSMI 1.2 extensions are supported only in 2.7 and later versions.
38 * PSMI 1.3 and 1.4 extensions are supported in Solaris 10.
39 * PSMI 1.5 extensions are supported in Solaris Nevada.
40 * PSMI 1.6 extensions are supported in Solaris Nevada.
41 * PSMI 1.7 extensions are supported in Solaris Nevada.
42 */
43 #define PSMI_1_7
44
45 #include <sys/processor.h>
46 #include <sys/time.h>
47 #include <sys/psm.h>
48 #include <sys/smp_impldefs.h>
56 #include <sys/sunddi.h>
57 #include <sys/ddi_impldefs.h>
58 #include <sys/pci.h>
59 #include <sys/promif.h>
60 #include <sys/x86_archext.h>
61 #include <sys/cpc_impl.h>
62 #include <sys/uadmin.h>
63 #include <sys/panic.h>
64 #include <sys/debug.h>
65 #include <sys/archsystm.h>
66 #include <sys/trap.h>
67 #include <sys/machsystm.h>
68 #include <sys/sysmacros.h>
69 #include <sys/cpuvar.h>
70 #include <sys/rm_platter.h>
71 #include <sys/privregs.h>
72 #include <sys/note.h>
73 #include <sys/pci_intr_lib.h>
74 #include <sys/spl.h>
75 #include <sys/clock.h>
76 #include <sys/dditypes.h>
77 #include <sys/sunddi.h>
78 #include <sys/x_call.h>
79 #include <sys/reboot.h>
80 #include <sys/hpet.h>
81 #include <sys/apic_common.h>
82 #include <sys/apic_timer.h>
83
84 /*
85 * Local Function Prototypes
86 */
87 static void apic_init_intr(void);
88
89 /*
90 * standard MP entries
91 */
92 static int apic_probe(void);
93 static int apic_getclkirq(int ipl);
94 static void apic_init(void);
95 static void apic_picinit(void);
977 }
978 }
979 }
980
981 if (apic_cpus[cpun].aci_status & APIC_CPU_SUSPEND)
982 apic_cpus[cpun].aci_status &= ~APIC_CPU_SUSPEND;
983
984 lock_clear(&apic_ioapic_lock);
985 intr_restore(iflag);
986 }
987
988 /*
989 * If this module needs a periodic handler for the interrupt distribution, it
990 * can be added here. The argument to the periodic handler is not currently
991 * used, but is reserved for future.
992 */
993 static void
994 apic_post_cyclic_setup(void *arg)
995 {
996 _NOTE(ARGUNUSED(arg))
997 /* cpu_lock is held */
998 /* set up a periodic handler for intr redistribution */
999
1000 /*
1001 * In peridoc mode intr redistribution processing is done in
1002 * apic_intr_enter during clk intr processing
1003 */
1004 if (!apic_oneshot)
1005 return;
1006 /*
1007 * Register a periodical handler for the redistribution processing.
1008 * On X86, CY_LOW_LEVEL is mapped to the level 2 interrupt, so
1009 * DDI_IPL_2 should be passed to ddi_periodic_add() here.
1010 */
1011 apic_periodic_id = ddi_periodic_add(
1012 (void (*)(void *))apic_redistribute_compute, NULL,
1013 apic_redistribute_sample_interval, DDI_IPL_2);
1014 }
1015
1016 static void
1017 apic_redistribute_compute(void)
1018 {
1019 int i, j, max_busy;
1020
1021 if (apic_enable_dynamic_migration) {
1022 if (++apic_nticks == apic_sample_factor_redistribution) {
1023 /*
1024 * Time to call apic_intr_redistribute().
1025 * reset apic_nticks. This will cause max_busy
1026 * to be calculated below and if it is more than
1027 * apic_int_busy, we will do the whole thing
1028 */
1029 apic_nticks = 0;
1030 }
1031 max_busy = 0;
1032 for (i = 0; i < apic_nproc; i++) {
1033 if (!apic_cpu_in_range(i))
|
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) 1993, 2010, Oracle and/or its affiliates. All rights reserved.
24 */
25 /*
26 * Copyright (c) 2010, Intel Corporation.
27 * All rights reserved.
28 */
29 /*
30 * Copyright (c) 2013, Joyent, Inc. All rights reserved.
31 */
32
33 /*
34 * To understand how the pcplusmp module interacts with the interrupt subsystem
35 * read the theory statement in uts/i86pc/os/intr.c.
36 */
37
38 /*
39 * PSMI 1.1 extensions are supported only in 2.6 and later versions.
40 * PSMI 1.2 extensions are supported only in 2.7 and later versions.
41 * PSMI 1.3 and 1.4 extensions are supported in Solaris 10.
42 * PSMI 1.5 extensions are supported in Solaris Nevada.
43 * PSMI 1.6 extensions are supported in Solaris Nevada.
44 * PSMI 1.7 extensions are supported in Solaris Nevada.
45 */
46 #define PSMI_1_7
47
48 #include <sys/processor.h>
49 #include <sys/time.h>
50 #include <sys/psm.h>
51 #include <sys/smp_impldefs.h>
59 #include <sys/sunddi.h>
60 #include <sys/ddi_impldefs.h>
61 #include <sys/pci.h>
62 #include <sys/promif.h>
63 #include <sys/x86_archext.h>
64 #include <sys/cpc_impl.h>
65 #include <sys/uadmin.h>
66 #include <sys/panic.h>
67 #include <sys/debug.h>
68 #include <sys/archsystm.h>
69 #include <sys/trap.h>
70 #include <sys/machsystm.h>
71 #include <sys/sysmacros.h>
72 #include <sys/cpuvar.h>
73 #include <sys/rm_platter.h>
74 #include <sys/privregs.h>
75 #include <sys/note.h>
76 #include <sys/pci_intr_lib.h>
77 #include <sys/spl.h>
78 #include <sys/clock.h>
79 #include <sys/cyclic.h>
80 #include <sys/dditypes.h>
81 #include <sys/sunddi.h>
82 #include <sys/x_call.h>
83 #include <sys/reboot.h>
84 #include <sys/hpet.h>
85 #include <sys/apic_common.h>
86 #include <sys/apic_timer.h>
87
88 /*
89 * Local Function Prototypes
90 */
91 static void apic_init_intr(void);
92
93 /*
94 * standard MP entries
95 */
96 static int apic_probe(void);
97 static int apic_getclkirq(int ipl);
98 static void apic_init(void);
99 static void apic_picinit(void);
981 }
982 }
983 }
984
985 if (apic_cpus[cpun].aci_status & APIC_CPU_SUSPEND)
986 apic_cpus[cpun].aci_status &= ~APIC_CPU_SUSPEND;
987
988 lock_clear(&apic_ioapic_lock);
989 intr_restore(iflag);
990 }
991
992 /*
993 * If this module needs a periodic handler for the interrupt distribution, it
994 * can be added here. The argument to the periodic handler is not currently
995 * used, but is reserved for future.
996 */
997 static void
998 apic_post_cyclic_setup(void *arg)
999 {
1000 _NOTE(ARGUNUSED(arg))
1001
1002 cyc_handler_t cyh;
1003 cyc_time_t cyt;
1004
1005 /* cpu_lock is held */
1006 /* set up a periodic handler for intr redistribution */
1007
1008 /*
1009 * In peridoc mode intr redistribution processing is done in
1010 * apic_intr_enter during clk intr processing
1011 */
1012 if (!apic_oneshot)
1013 return;
1014
1015 /*
1016 * Register a periodical handler for the redistribution processing.
1017 * Though we would generally prefer to use the DDI interface for
1018 * periodic handler invocation, ddi_periodic_add(9F), we are
1019 * unfortunately already holding cpu_lock, which ddi_periodic_add will
1020 * attempt to take for us. Thus, we add our own cyclic directly:
1021 */
1022 cyh.cyh_func = (void (*)(void *))apic_redistribute_compute;
1023 cyh.cyh_arg = NULL;
1024 cyh.cyh_level = CY_LOW_LEVEL;
1025
1026 cyt.cyt_when = 0;
1027 cyt.cyt_interval = apic_redistribute_sample_interval;
1028
1029 apic_cyclic_id = cyclic_add(&cyh, &cyt);
1030 }
1031
1032 static void
1033 apic_redistribute_compute(void)
1034 {
1035 int i, j, max_busy;
1036
1037 if (apic_enable_dynamic_migration) {
1038 if (++apic_nticks == apic_sample_factor_redistribution) {
1039 /*
1040 * Time to call apic_intr_redistribute().
1041 * reset apic_nticks. This will cause max_busy
1042 * to be calculated below and if it is more than
1043 * apic_int_busy, we will do the whole thing
1044 */
1045 apic_nticks = 0;
1046 }
1047 max_busy = 0;
1048 for (i = 0; i < apic_nproc; i++) {
1049 if (!apic_cpu_in_range(i))
|