]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/x86/xen/pvcpu_enum.c
Update mandoc to 1.13.1
[FreeBSD/FreeBSD.git] / sys / x86 / xen / pvcpu_enum.c
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$");
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/actables.h>
54
55 #include <dev/acpica/acpivar.h>
56
57 static int xenpv_probe(void);
58 static int xenpv_probe_cpus(void);
59 static int xenpv_setup_local(void);
60 static int xenpv_setup_io(void);
61
62 static ACPI_TABLE_MADT *madt;
63 static vm_paddr_t madt_physaddr;
64 static vm_offset_t madt_length;
65
66 static struct apic_enumerator xenpv_enumerator = {
67         "Xen PV",
68         xenpv_probe,
69         xenpv_probe_cpus,
70         xenpv_setup_local,
71         xenpv_setup_io
72 };
73
74 /*--------------------- Helper functions to parse MADT -----------------------*/
75
76 /*
77  * Parse an interrupt source override for an ISA interrupt.
78  */
79 static void
80 madt_parse_interrupt_override(ACPI_MADT_INTERRUPT_OVERRIDE *intr)
81 {
82         enum intr_trigger trig;
83         enum intr_polarity pol;
84
85         if (acpi_quirks & ACPI_Q_MADT_IRQ0 && intr->SourceIrq == 0 &&
86             intr->GlobalIrq == 2) {
87                 if (bootverbose)
88                         printf("MADT: Skipping timer override\n");
89                 return;
90         }
91
92         madt_parse_interrupt_values(intr, &trig, &pol);
93
94         /* Register the IRQ with the polarity and trigger mode found. */
95         xen_register_pirq(intr->GlobalIrq, trig, pol);
96 }
97
98 /*
99  * Call the handler routine for each entry in the MADT table.
100  */
101 static void
102 madt_walk_table(acpi_subtable_handler *handler, void *arg)
103 {
104
105         acpi_walk_subtables(madt + 1, (char *)madt + madt->Header.Length,
106             handler, arg);
107 }
108
109 /*
110  * Parse interrupt entries.
111  */
112 static void
113 madt_parse_ints(ACPI_SUBTABLE_HEADER *entry, void *arg __unused)
114 {
115
116         if (entry->Type == ACPI_MADT_TYPE_INTERRUPT_OVERRIDE)
117                 madt_parse_interrupt_override(
118                     (ACPI_MADT_INTERRUPT_OVERRIDE *)entry);
119 }
120
121 /*---------------------------- Xen PV enumerator -----------------------------*/
122
123 /*
124  * This enumerator will only be registered on PVH
125  */
126 static int
127 xenpv_probe(void)
128 {
129         return (0);
130 }
131
132 /*
133  * Test each possible vCPU in order to find the number of vCPUs
134  */
135 static int
136 xenpv_probe_cpus(void)
137 {
138 #ifdef SMP
139         int i, ret;
140
141         for (i = 0; i < MAXCPU; i++) {
142                 ret = HYPERVISOR_vcpu_op(VCPUOP_is_up, i, NULL);
143                 if (ret >= 0)
144                         lapic_create((i * 2), (i == 0));
145         }
146 #endif
147         return (0);
148 }
149
150 /*
151  * Initialize the vCPU id of the BSP
152  */
153 static int
154 xenpv_setup_local(void)
155 {
156         PCPU_SET(vcpu_id, 0);
157         lapic_init(0);
158         return (0);
159 }
160
161 /*
162  * On PVH guests there's no IO APIC
163  */
164 static int
165 xenpv_setup_io(void)
166 {
167
168         if (xen_initial_domain()) {
169                 int i;
170
171                 /* Map MADT */
172                 madt_physaddr = acpi_find_table(ACPI_SIG_MADT);
173                 madt = acpi_map_table(madt_physaddr, ACPI_SIG_MADT);
174                 madt_length = madt->Header.Length;
175
176                 /* Try to initialize ACPI so that we can access the FADT. */
177                 i = acpi_Startup();
178                 if (ACPI_FAILURE(i)) {
179                         printf("MADT: ACPI Startup failed with %s\n",
180                             AcpiFormatException(i));
181                         printf("Try disabling either ACPI or apic support.\n");
182                         panic("Using MADT but ACPI doesn't work");
183                 }
184
185                 /* Run through the table to see if there are any overrides. */
186                 madt_walk_table(madt_parse_ints, NULL);
187
188                 /*
189                  * If there was not an explicit override entry for the SCI,
190                  * force it to use level trigger and active-low polarity.
191                  */
192                 if (!madt_found_sci_override) {
193                         printf(
194         "MADT: Forcing active-low polarity and level trigger for SCI\n");
195                         xen_register_pirq(AcpiGbl_FADT.SciInterrupt,
196                             INTR_TRIGGER_LEVEL, INTR_POLARITY_LOW);
197                 }
198
199                 acpi_SetDefaultIntrModel(ACPI_INTR_APIC);
200         }
201         return (0);
202 }
203
204 static void
205 xenpv_register(void *dummy __unused)
206 {
207         if (xen_pv_domain()) {
208                 apic_register_enumerator(&xenpv_enumerator);
209         }
210 }
211 SYSINIT(xenpv_register, SI_SUB_TUNABLES - 1, SI_ORDER_FIRST, xenpv_register, NULL);
212
213 /*
214  * Setup per-CPU vCPU IDs
215  */
216 static void
217 xenpv_set_ids(void *dummy)
218 {
219         struct pcpu *pc;
220         int i;
221
222         CPU_FOREACH(i) {
223                 pc = pcpu_find(i);
224                 pc->pc_vcpu_id = i;
225         }
226 }
227 SYSINIT(xenpv_set_ids, SI_SUB_CPU, SI_ORDER_MIDDLE, xenpv_set_ids, NULL);