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


   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))