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 2013 Nexenta Systems, Inc. All rights reserved.
31 * Copyright 2013 Pluribus Networks, Inc.
32 */
33
34 #include <sys/processor.h>
35 #include <sys/time.h>
36 #include <sys/psm.h>
37 #include <sys/smp_impldefs.h>
38 #include <sys/cram.h>
39 #include <sys/acpi/acpi.h>
40 #include <sys/acpica.h>
41 #include <sys/psm_common.h>
42 #include <sys/pit.h>
43 #include <sys/ddi.h>
44 #include <sys/sunddi.h>
45 #include <sys/ddi_impldefs.h>
46 #include <sys/pci.h>
47 #include <sys/promif.h>
48 #include <sys/x86_archext.h>
49 #include <sys/cpc_impl.h>
50 #include <sys/uadmin.h>
51 #include <sys/panic.h>
52 #include <sys/debug.h>
53 #include <sys/archsystm.h>
54 #include <sys/trap.h>
55 #include <sys/machsystm.h>
56 #include <sys/sysmacros.h>
57 #include <sys/cpuvar.h>
58 #include <sys/rm_platter.h>
59 #include <sys/privregs.h>
60 #include <sys/note.h>
61 #include <sys/pci_intr_lib.h>
62 #include <sys/spl.h>
63 #include <sys/clock.h>
64 #include <sys/dditypes.h>
65 #include <sys/sunddi.h>
66 #include <sys/x_call.h>
67 #include <sys/reboot.h>
68 #include <sys/apix.h>
69
70 static int apix_get_avail_vector_oncpu(uint32_t, int, int);
71 static apix_vector_t *apix_init_vector(processorid_t, uchar_t);
72 static void apix_cleanup_vector(apix_vector_t *);
73 static void apix_insert_av(apix_vector_t *, void *, avfunc, caddr_t, caddr_t,
74 uint64_t *, int, dev_info_t *);
75 static void apix_remove_av(apix_vector_t *, struct autovec *);
76 static void apix_clear_dev_map(dev_info_t *, int, int);
77 static boolean_t apix_is_cpu_enabled(processorid_t);
78 static void apix_wait_till_seen(processorid_t, int);
79
80 #define GET_INTR_INUM(ihdlp) \
81 (((ihdlp) != NULL) ? ((ddi_intr_handle_impl_t *)(ihdlp))->ih_inum : 0)
82
83 apix_rebind_info_t apix_rebindinfo = {0, 0, 0, NULL, 0, NULL};
84
85 /*
86 * Allocate IPI
87 *
88 * Return vector number or 0 on error
786 /*
787 * Insert an interrupt service routine into chain by its priority from
788 * high to low
789 */
790 static void
791 apix_insert_av(apix_vector_t *vecp, void *intr_id, avfunc f, caddr_t arg1,
792 caddr_t arg2, uint64_t *ticksp, int ipl, dev_info_t *dip)
793 {
794 struct autovec *p, *prep, *mem;
795
796 APIC_VERBOSE(INTR, (CE_CONT, "apix_insert_av: dip %p, vector 0x%x, "
797 "cpu %d\n", (void *)dip, vecp->v_vector, vecp->v_cpuid));
798
799 mem = kmem_zalloc(sizeof (struct autovec), KM_SLEEP);
800 INIT_AUTOVEC(mem, intr_id, f, arg1, arg2, ticksp, ipl, dip);
801 if (vecp->v_type == APIX_TYPE_FIXED && apic_level_intr[vecp->v_inum])
802 mem->av_flags |= AV_PENTRY_LEVEL;
803
804 vecp->v_share++;
805 vecp->v_pri = (ipl > vecp->v_pri) ? ipl : vecp->v_pri;
806 if (vecp->v_autovect == NULL) { /* Nothing on list - put it at head */
807 vecp->v_autovect = mem;
808 return;
809 }
810
811 if (DDI_INTR_IS_MSI_OR_MSIX(vecp->v_type)) { /* MSI/X */
812 ASSERT(vecp->v_share == 1); /* No sharing for MSI/X */
813
814 INIT_AUTOVEC(vecp->v_autovect, intr_id, f, arg1, arg2, ticksp,
815 ipl, dip);
816 prep = vecp->v_autovect->av_link;
817 vecp->v_autovect->av_link = NULL;
818
819 /* Free the following autovect chain */
820 while (prep != NULL) {
821 ASSERT(prep->av_vector == NULL);
822
823 p = prep;
824 prep = prep->av_link;
825 kmem_free(p, sizeof (struct autovec));
|
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 2013 Nexenta Systems, Inc. All rights reserved.
31 * Copyright 2013 Pluribus Networks, Inc.
32 * Copyright 2018 Joyent, Inc.
33 */
34
35 #include <sys/processor.h>
36 #include <sys/time.h>
37 #include <sys/psm.h>
38 #include <sys/smp_impldefs.h>
39 #include <sys/cram.h>
40 #include <sys/acpi/acpi.h>
41 #include <sys/acpica.h>
42 #include <sys/psm_common.h>
43 #include <sys/pit.h>
44 #include <sys/ddi.h>
45 #include <sys/sunddi.h>
46 #include <sys/ddi_impldefs.h>
47 #include <sys/pci.h>
48 #include <sys/promif.h>
49 #include <sys/x86_archext.h>
50 #include <sys/cpc_impl.h>
51 #include <sys/uadmin.h>
52 #include <sys/panic.h>
53 #include <sys/debug.h>
54 #include <sys/archsystm.h>
55 #include <sys/trap.h>
56 #include <sys/machsystm.h>
57 #include <sys/sysmacros.h>
58 #include <sys/cpuvar.h>
59 #include <sys/rm_platter.h>
60 #include <sys/privregs.h>
61 #include <sys/note.h>
62 #include <sys/pci_intr_lib.h>
63 #include <sys/spl.h>
64 #include <sys/clock.h>
65 #include <sys/dditypes.h>
66 #include <sys/sunddi.h>
67 #include <sys/x_call.h>
68 #include <sys/reboot.h>
69 #include <sys/apix.h>
70 #include <sys/ht.h>
71
72 static int apix_get_avail_vector_oncpu(uint32_t, int, int);
73 static apix_vector_t *apix_init_vector(processorid_t, uchar_t);
74 static void apix_cleanup_vector(apix_vector_t *);
75 static void apix_insert_av(apix_vector_t *, void *, avfunc, caddr_t, caddr_t,
76 uint64_t *, int, dev_info_t *);
77 static void apix_remove_av(apix_vector_t *, struct autovec *);
78 static void apix_clear_dev_map(dev_info_t *, int, int);
79 static boolean_t apix_is_cpu_enabled(processorid_t);
80 static void apix_wait_till_seen(processorid_t, int);
81
82 #define GET_INTR_INUM(ihdlp) \
83 (((ihdlp) != NULL) ? ((ddi_intr_handle_impl_t *)(ihdlp))->ih_inum : 0)
84
85 apix_rebind_info_t apix_rebindinfo = {0, 0, 0, NULL, 0, NULL};
86
87 /*
88 * Allocate IPI
89 *
90 * Return vector number or 0 on error
788 /*
789 * Insert an interrupt service routine into chain by its priority from
790 * high to low
791 */
792 static void
793 apix_insert_av(apix_vector_t *vecp, void *intr_id, avfunc f, caddr_t arg1,
794 caddr_t arg2, uint64_t *ticksp, int ipl, dev_info_t *dip)
795 {
796 struct autovec *p, *prep, *mem;
797
798 APIC_VERBOSE(INTR, (CE_CONT, "apix_insert_av: dip %p, vector 0x%x, "
799 "cpu %d\n", (void *)dip, vecp->v_vector, vecp->v_cpuid));
800
801 mem = kmem_zalloc(sizeof (struct autovec), KM_SLEEP);
802 INIT_AUTOVEC(mem, intr_id, f, arg1, arg2, ticksp, ipl, dip);
803 if (vecp->v_type == APIX_TYPE_FIXED && apic_level_intr[vecp->v_inum])
804 mem->av_flags |= AV_PENTRY_LEVEL;
805
806 vecp->v_share++;
807 vecp->v_pri = (ipl > vecp->v_pri) ? ipl : vecp->v_pri;
808
809 ht_intr_alloc_pil(vecp->v_pri);
810
811 if (vecp->v_autovect == NULL) { /* Nothing on list - put it at head */
812 vecp->v_autovect = mem;
813 return;
814 }
815
816 if (DDI_INTR_IS_MSI_OR_MSIX(vecp->v_type)) { /* MSI/X */
817 ASSERT(vecp->v_share == 1); /* No sharing for MSI/X */
818
819 INIT_AUTOVEC(vecp->v_autovect, intr_id, f, arg1, arg2, ticksp,
820 ipl, dip);
821 prep = vecp->v_autovect->av_link;
822 vecp->v_autovect->av_link = NULL;
823
824 /* Free the following autovect chain */
825 while (prep != NULL) {
826 ASSERT(prep->av_vector == NULL);
827
828 p = prep;
829 prep = prep->av_link;
830 kmem_free(p, sizeof (struct autovec));
|