Print this page
OS-7125 Need mitigation of L1TF (CVE-2018-3646)
Reviewed by: Robert Mustacchi <rm@joyent.com>
Reviewed by: Jerry Jelinek <jerry.jelinek@joyent.com>


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