The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/x86/xen/pvcpu_enum.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*-
    2  * Copyright (c) 2003 John Baldwin <jhb@FreeBSD.org>
    3  * Copyright (c) 2013 Roger Pau Monné <roger.pau@citrix.com>
    4  * All rights reserved.
    5  *
    6  * Redistribution and use in source and binary forms, with or without
    7  * modification, are permitted provided that the following conditions
    8  * are met:
    9  * 1. Redistributions of source code must retain the above copyright
   10  *    notice, this list of conditions and the following disclaimer.
   11  * 2. Redistributions in binary form must reproduce the above copyright
   12  *    notice, this list of conditions and the following disclaimer in the
   13  *    documentation and/or other materials provided with the distribution.
   14  *
   15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   18  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   19  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   21  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   23  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   25  * SUCH DAMAGE.
   26  */
   27 
   28 #include <sys/cdefs.h>
   29 __FBSDID("$FreeBSD: releng/11.2/sys/x86/xen/pvcpu_enum.c 316303 2017-03-30 20:18:34Z jkim $");
   30 
   31 #include <sys/param.h>
   32 #include <sys/systm.h>
   33 #include <sys/bus.h>
   34 #include <sys/kernel.h>
   35 #include <sys/smp.h>
   36 #include <sys/pcpu.h>
   37 #include <vm/vm.h>
   38 #include <vm/pmap.h>
   39 
   40 #include <machine/intr_machdep.h>
   41 #include <x86/apicvar.h>
   42 
   43 #include <machine/cpu.h>
   44 #include <machine/smp.h>
   45 
   46 #include <xen/xen-os.h>
   47 #include <xen/xen_intr.h>
   48 #include <xen/hypervisor.h>
   49 
   50 #include <xen/interface/vcpu.h>
   51 
   52 #include <contrib/dev/acpica/include/acpi.h>
   53 #include <contrib/dev/acpica/include/aclocal.h>
   54 #include <contrib/dev/acpica/include/actables.h>
   55 
   56 #include <dev/acpica/acpivar.h>
   57 
   58 static int xenpv_probe(void);
   59 static int xenpv_probe_cpus(void);
   60 static int xenpv_setup_local(void);
   61 static int xenpv_setup_io(void);
   62 
   63 static ACPI_TABLE_MADT *madt;
   64 static vm_paddr_t madt_physaddr;
   65 static vm_offset_t madt_length;
   66 
   67 static struct apic_enumerator xenpv_enumerator = {
   68         "Xen PV",
   69         xenpv_probe,
   70         xenpv_probe_cpus,
   71         xenpv_setup_local,
   72         xenpv_setup_io
   73 };
   74 
   75 /*--------------------- Helper functions to parse MADT -----------------------*/
   76 
   77 /*
   78  * Parse an interrupt source override for an ISA interrupt.
   79  */
   80 static void
   81 madt_parse_interrupt_override(ACPI_MADT_INTERRUPT_OVERRIDE *intr)
   82 {
   83         enum intr_trigger trig;
   84         enum intr_polarity pol;
   85         int ret;
   86 
   87         if (acpi_quirks & ACPI_Q_MADT_IRQ0 && intr->SourceIrq == 0 &&
   88             intr->GlobalIrq == 2) {
   89                 if (bootverbose)
   90                         printf("MADT: Skipping timer override\n");
   91                 return;
   92         }
   93 
   94         madt_parse_interrupt_values(intr, &trig, &pol);
   95 
   96         /* Remap the IRQ if it is mapped to a different interrupt vector. */
   97         if (intr->SourceIrq != intr->GlobalIrq && intr->GlobalIrq > 15 &&
   98             intr->SourceIrq == AcpiGbl_FADT.SciInterrupt)
   99                 /*
  100                  * If the SCI is remapped to a non-ISA global interrupt,
  101                  * then override the vector we use to setup.
  102                  */
  103                 acpi_OverrideInterruptLevel(intr->GlobalIrq);
  104 
  105         /* Register the IRQ with the polarity and trigger mode found. */
  106         ret = xen_register_pirq(intr->GlobalIrq, trig, pol);
  107         if (ret != 0)
  108                 panic("Unable to register interrupt override");
  109 }
  110 
  111 /*
  112  * Call the handler routine for each entry in the MADT table.
  113  */
  114 static void
  115 madt_walk_table(acpi_subtable_handler *handler, void *arg)
  116 {
  117 
  118         acpi_walk_subtables(madt + 1, (char *)madt + madt->Header.Length,
  119             handler, arg);
  120 }
  121 
  122 /*
  123  * Parse interrupt entries.
  124  */
  125 static void
  126 madt_parse_ints(ACPI_SUBTABLE_HEADER *entry, void *arg __unused)
  127 {
  128 
  129         if (entry->Type == ACPI_MADT_TYPE_INTERRUPT_OVERRIDE)
  130                 madt_parse_interrupt_override(
  131                     (ACPI_MADT_INTERRUPT_OVERRIDE *)entry);
  132 }
  133 
  134 /*---------------------------- Xen PV enumerator -----------------------------*/
  135 
  136 /*
  137  * This enumerator will only be registered on PVH
  138  */
  139 static int
  140 xenpv_probe(void)
  141 {
  142         return (0);
  143 }
  144 
  145 /*
  146  * Test each possible vCPU in order to find the number of vCPUs
  147  */
  148 static int
  149 xenpv_probe_cpus(void)
  150 {
  151 #ifdef SMP
  152         int i, ret;
  153 
  154         for (i = 0; i < MAXCPU; i++) {
  155                 ret = HYPERVISOR_vcpu_op(VCPUOP_is_up, i, NULL);
  156                 if (ret >= 0)
  157                         lapic_create((i * 2), (i == 0));
  158         }
  159 #endif
  160         return (0);
  161 }
  162 
  163 /*
  164  * Initialize the vCPU id of the BSP
  165  */
  166 static int
  167 xenpv_setup_local(void)
  168 {
  169         PCPU_SET(vcpu_id, 0);
  170         lapic_init(0);
  171         return (0);
  172 }
  173 
  174 /*
  175  * On PVH guests there's no IO APIC
  176  */
  177 static int
  178 xenpv_setup_io(void)
  179 {
  180 
  181         if (xen_initial_domain()) {
  182                 int i, ret;
  183 
  184                 /* Map MADT */
  185                 madt_physaddr = acpi_find_table(ACPI_SIG_MADT);
  186                 madt = acpi_map_table(madt_physaddr, ACPI_SIG_MADT);
  187                 madt_length = madt->Header.Length;
  188 
  189                 /* Try to initialize ACPI so that we can access the FADT. */
  190                 i = acpi_Startup();
  191                 if (ACPI_FAILURE(i)) {
  192                         printf("MADT: ACPI Startup failed with %s\n",
  193                             AcpiFormatException(i));
  194                         printf("Try disabling either ACPI or apic support.\n");
  195                         panic("Using MADT but ACPI doesn't work");
  196                 }
  197 
  198                 /* Run through the table to see if there are any overrides. */
  199                 madt_walk_table(madt_parse_ints, NULL);
  200 
  201                 /*
  202                  * If there was not an explicit override entry for the SCI,
  203                  * force it to use level trigger and active-low polarity.
  204                  */
  205                 if (!madt_found_sci_override) {
  206                         printf(
  207         "MADT: Forcing active-low polarity and level trigger for SCI\n");
  208                         ret = xen_register_pirq(AcpiGbl_FADT.SciInterrupt,
  209                             INTR_TRIGGER_LEVEL, INTR_POLARITY_LOW);
  210                         if (ret != 0)
  211                                 panic("Unable to register SCI IRQ");
  212                 }
  213 
  214                 /* Register legacy ISA IRQs */
  215                 for (i = 1; i < 16; i++) {
  216                         if (intr_lookup_source(i) != NULL)
  217                                 continue;
  218                         ret = xen_register_pirq(i, INTR_TRIGGER_EDGE,
  219                             INTR_POLARITY_LOW);
  220                         if (ret != 0 && bootverbose)
  221                                 printf("Unable to register legacy IRQ#%d: %d\n",
  222                                     i, ret);
  223                 }
  224 
  225                 acpi_SetDefaultIntrModel(ACPI_INTR_APIC);
  226         }
  227         return (0);
  228 }
  229 
  230 static void
  231 xenpv_register(void *dummy __unused)
  232 {
  233         if (xen_pv_domain()) {
  234                 apic_register_enumerator(&xenpv_enumerator);
  235         }
  236 }
  237 SYSINIT(xenpv_register, SI_SUB_TUNABLES - 1, SI_ORDER_FIRST, xenpv_register, NULL);
  238 
  239 /*
  240  * Setup per-CPU vCPU IDs
  241  */
  242 static void
  243 xenpv_set_ids(void *dummy)
  244 {
  245         struct pcpu *pc;
  246         int i;
  247 
  248         CPU_FOREACH(i) {
  249                 pc = pcpu_find(i);
  250                 pc->pc_vcpu_id = i;
  251         }
  252 }
  253 SYSINIT(xenpv_set_ids, SI_SUB_CPU, SI_ORDER_MIDDLE, xenpv_set_ids, NULL);

Cache object: a151e0b9c2d88f4cf501a7de5f34a90d


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.