Print this page
OS-2366 ddi_periodic_add(9F) is entirely rubbish


  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) 2010, Intel Corporation.
  27  * All rights reserved.
  28  */
  29 /*
  30  * Copyright (c) 2012, Joyent, Inc.  All rights reserved.
  31  */
  32 
  33 /*
  34  * To understand how the apix module interacts with the interrupt subsystem read
  35  * 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>


  58 #include <sys/sunddi.h>
  59 #include <sys/ddi_impldefs.h>
  60 #include <sys/pci.h>
  61 #include <sys/promif.h>
  62 #include <sys/x86_archext.h>
  63 #include <sys/cpc_impl.h>
  64 #include <sys/uadmin.h>
  65 #include <sys/panic.h>
  66 #include <sys/debug.h>
  67 #include <sys/archsystm.h>
  68 #include <sys/trap.h>
  69 #include <sys/machsystm.h>
  70 #include <sys/sysmacros.h>
  71 #include <sys/cpuvar.h>
  72 #include <sys/rm_platter.h>
  73 #include <sys/privregs.h>
  74 #include <sys/note.h>
  75 #include <sys/pci_intr_lib.h>
  76 #include <sys/spl.h>
  77 #include <sys/clock.h>

  78 #include <sys/dditypes.h>
  79 #include <sys/sunddi.h>
  80 #include <sys/x_call.h>
  81 #include <sys/reboot.h>
  82 #include <sys/mach_intr.h>
  83 #include <sys/apix.h>
  84 #include <sys/apix_irm_impl.h>
  85 
  86 static int apix_probe();
  87 static void apix_init();
  88 static void apix_picinit(void);
  89 static int apix_intr_enter(int, int *);
  90 static void apix_intr_exit(int, int);
  91 static void apix_setspl(int);
  92 static int apix_disable_intr(processorid_t);
  93 static void apix_enable_intr(processorid_t);
  94 static int apix_get_clkvect(int);
  95 static int apix_get_ipivect(int, int);
  96 static void apix_post_cyclic_setup(void *);
  97 static int apix_post_cpu_start();


1055          * APIC_CPU_ONLINE flag here rather than setting aci_status completely.
1056          */
1057         cpun = psm_get_cpu_id();
1058         apic_cpus[cpun].aci_status |= APIC_CPU_ONLINE;
1059 
1060         apic_reg_ops->apic_write(APIC_DIVIDE_REG, apic_divide_reg_init);
1061 
1062         return (PSM_SUCCESS);
1063 }
1064 
1065 /*
1066  * If this module needs a periodic handler for the interrupt distribution, it
1067  * can be added here. The argument to the periodic handler is not currently
1068  * used, but is reserved for future.
1069  */
1070 static void
1071 apix_post_cyclic_setup(void *arg)
1072 {
1073         UNREFERENCED_1PARAMETER(arg);
1074 



1075         /* cpu_lock is held */
1076         /* set up a periodic handler for intr redistribution */
1077 
1078         /*
1079          * In peridoc mode intr redistribution processing is done in
1080          * apic_intr_enter during clk intr processing
1081          */
1082         if (!apic_oneshot)
1083                 return;
1084 
1085         /*
1086          * Register a periodical handler for the redistribution processing.
1087          * On X86, CY_LOW_LEVEL is mapped to the level 2 interrupt, so
1088          * DDI_IPL_2 should be passed to ddi_periodic_add() here.


1089          */
1090         apic_periodic_id = ddi_periodic_add(
1091             (void (*)(void *))apix_redistribute_compute, NULL,
1092             apic_redistribute_sample_interval, DDI_IPL_2);





1093 }
1094 
1095 /*
1096  * Called the first time we enable x2apic mode on this cpu.
1097  * Update some of the function pointers to use x2apic routines.
1098  */
1099 void
1100 x2apic_update_psm()
1101 {
1102         struct psm_ops *pops = &apix_ops;
1103 
1104         ASSERT(pops != NULL);
1105 
1106         /*
1107          * The pcplusmp module's version of x2apic_update_psm makes additional
1108          * changes that we do not have to make here. It needs to make those
1109          * changes because pcplusmp relies on the TPR register and the means of
1110          * addressing that changes when using the local apic versus the x2apic.
1111          * It's also worth noting that the apix driver specific function end up
1112          * being apix_foo as opposed to apic_foo and x2apic_foo.




  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) 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 apix module interacts with the interrupt subsystem read
  35  * 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>


  58 #include <sys/sunddi.h>
  59 #include <sys/ddi_impldefs.h>
  60 #include <sys/pci.h>
  61 #include <sys/promif.h>
  62 #include <sys/x86_archext.h>
  63 #include <sys/cpc_impl.h>
  64 #include <sys/uadmin.h>
  65 #include <sys/panic.h>
  66 #include <sys/debug.h>
  67 #include <sys/archsystm.h>
  68 #include <sys/trap.h>
  69 #include <sys/machsystm.h>
  70 #include <sys/sysmacros.h>
  71 #include <sys/cpuvar.h>
  72 #include <sys/rm_platter.h>
  73 #include <sys/privregs.h>
  74 #include <sys/note.h>
  75 #include <sys/pci_intr_lib.h>
  76 #include <sys/spl.h>
  77 #include <sys/clock.h>
  78 #include <sys/cyclic.h>
  79 #include <sys/dditypes.h>
  80 #include <sys/sunddi.h>
  81 #include <sys/x_call.h>
  82 #include <sys/reboot.h>
  83 #include <sys/mach_intr.h>
  84 #include <sys/apix.h>
  85 #include <sys/apix_irm_impl.h>
  86 
  87 static int apix_probe();
  88 static void apix_init();
  89 static void apix_picinit(void);
  90 static int apix_intr_enter(int, int *);
  91 static void apix_intr_exit(int, int);
  92 static void apix_setspl(int);
  93 static int apix_disable_intr(processorid_t);
  94 static void apix_enable_intr(processorid_t);
  95 static int apix_get_clkvect(int);
  96 static int apix_get_ipivect(int, int);
  97 static void apix_post_cyclic_setup(void *);
  98 static int apix_post_cpu_start();


1056          * APIC_CPU_ONLINE flag here rather than setting aci_status completely.
1057          */
1058         cpun = psm_get_cpu_id();
1059         apic_cpus[cpun].aci_status |= APIC_CPU_ONLINE;
1060 
1061         apic_reg_ops->apic_write(APIC_DIVIDE_REG, apic_divide_reg_init);
1062 
1063         return (PSM_SUCCESS);
1064 }
1065 
1066 /*
1067  * If this module needs a periodic handler for the interrupt distribution, it
1068  * can be added here. The argument to the periodic handler is not currently
1069  * used, but is reserved for future.
1070  */
1071 static void
1072 apix_post_cyclic_setup(void *arg)
1073 {
1074         UNREFERENCED_1PARAMETER(arg);
1075 
1076         cyc_handler_t cyh;
1077         cyc_time_t cyt;
1078 
1079         /* cpu_lock is held */
1080         /* set up a periodic handler for intr redistribution */
1081 
1082         /*
1083          * In peridoc mode intr redistribution processing is done in
1084          * apic_intr_enter during clk intr processing
1085          */
1086         if (!apic_oneshot)
1087                 return;
1088 
1089         /*
1090          * Register a periodical handler for the redistribution processing.
1091          * Though we would generally prefer to use the DDI interface for
1092          * periodic handler invocation, ddi_periodic_add(9F), we are
1093          * unfortunately already holding cpu_lock, which ddi_periodic_add will
1094          * attempt to take for us.  Thus, we add our own cyclic directly:
1095          */
1096         cyh.cyh_func = (void (*)(void *))apix_redistribute_compute;
1097         cyh.cyh_arg = NULL;
1098         cyh.cyh_level = CY_LOW_LEVEL;
1099 
1100         cyt.cyt_when = 0;
1101         cyt.cyt_interval = apic_redistribute_sample_interval;
1102 
1103         apic_cyclic_id = cyclic_add(&cyh, &cyt);
1104 }
1105 
1106 /*
1107  * Called the first time we enable x2apic mode on this cpu.
1108  * Update some of the function pointers to use x2apic routines.
1109  */
1110 void
1111 x2apic_update_psm()
1112 {
1113         struct psm_ops *pops = &apix_ops;
1114 
1115         ASSERT(pops != NULL);
1116 
1117         /*
1118          * The pcplusmp module's version of x2apic_update_psm makes additional
1119          * changes that we do not have to make here. It needs to make those
1120          * changes because pcplusmp relies on the TPR register and the means of
1121          * addressing that changes when using the local apic versus the x2apic.
1122          * It's also worth noting that the apix driver specific function end up
1123          * being apix_foo as opposed to apic_foo and x2apic_foo.