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) 2013 Roger Pau Monné <roger.pau@citrix.com>
    3  * All rights reserved.
    4  * Copyright (c) 2003 John Baldwin <jhb@FreeBSD.org>
    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$");
   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                 /*
  183                  * NB: we could iterate over the MADT IOAPIC entries in order
  184                  * to figure out the exact number of IOAPIC interrupts, but
  185                  * this is legacy code so just keep using the previous
  186                  * behaviour and assume a maximum of 256 interrupts.
  187                  */
  188                 num_io_irqs = max(MINIMUM_MSI_INT - 1, num_io_irqs);
  189 
  190                 acpi_SetDefaultIntrModel(ACPI_INTR_APIC);
  191         }
  192         return (0);
  193 }
  194 
  195 void
  196 xenpv_register_pirqs(struct pic *pic __unused)
  197 {
  198         unsigned int i;
  199         int ret;
  200 
  201         /* Map MADT */
  202         madt_physaddr = acpi_find_table(ACPI_SIG_MADT);
  203         madt = acpi_map_table(madt_physaddr, ACPI_SIG_MADT);
  204         madt_length = madt->Header.Length;
  205 
  206         /* Try to initialize ACPI so that we can access the FADT. */
  207         ret = acpi_Startup();
  208         if (ACPI_FAILURE(ret)) {
  209                 printf("MADT: ACPI Startup failed with %s\n",
  210                     AcpiFormatException(ret));
  211                 printf("Try disabling either ACPI or apic support.\n");
  212                 panic("Using MADT but ACPI doesn't work");
  213         }
  214 
  215         /* Run through the table to see if there are any overrides. */
  216         madt_walk_table(madt_parse_ints, NULL);
  217 
  218         /*
  219          * If there was not an explicit override entry for the SCI,
  220          * force it to use level trigger and active-low polarity.
  221          */
  222         if (!madt_found_sci_override) {
  223                 printf(
  224 "MADT: Forcing active-low polarity and level trigger for SCI\n");
  225                 ret = xen_register_pirq(AcpiGbl_FADT.SciInterrupt,
  226                     INTR_TRIGGER_LEVEL, INTR_POLARITY_LOW);
  227                 if (ret != 0)
  228                         panic("Unable to register SCI IRQ");
  229         }
  230 
  231         /* Register legacy ISA IRQs */
  232         for (i = 1; i < 16; i++) {
  233                 if (intr_lookup_source(i) != NULL)
  234                         continue;
  235                 ret = xen_register_pirq(i, INTR_TRIGGER_EDGE,
  236                     INTR_POLARITY_LOW);
  237                 if (ret != 0 && bootverbose)
  238                         printf("Unable to register legacy IRQ#%u: %d\n", i,
  239                             ret);
  240         }
  241 }
  242 
  243 static void
  244 xenpv_register(void *dummy __unused)
  245 {
  246         if (xen_pv_domain()) {
  247                 apic_register_enumerator(&xenpv_enumerator);
  248         }
  249 }
  250 SYSINIT(xenpv_register, SI_SUB_TUNABLES - 1, SI_ORDER_FIRST, xenpv_register, NULL);
  251 
  252 /*
  253  * Setup per-CPU vCPU IDs
  254  */
  255 static void
  256 xenpv_set_ids(void *dummy)
  257 {
  258         struct pcpu *pc;
  259         int i;
  260 
  261         CPU_FOREACH(i) {
  262                 pc = pcpu_find(i);
  263                 pc->pc_vcpu_id = i;
  264         }
  265 }
  266 SYSINIT(xenpv_set_ids, SI_SUB_CPU, SI_ORDER_MIDDLE, xenpv_set_ids, NULL);

Cache object: fe3502534aca79c450912733d2986eed


[ 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.