1/* $NetBSD: hypervisor.c,v 1.69 2016/07/11 11:31:50 msaitoh Exp $ */
2
3/*
4 * Copyright (c) 2005 Manuel Bouyer.
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 ``AS IS'' AND ANY EXPRESS OR
16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 *
26 */
27
28/*
29 *
30 * Copyright (c) 2004 Christian Limpach.
31 * All rights reserved.
32 *
33 * Redistribution and use in source and binary forms, with or without
34 * modification, are permitted provided that the following conditions
35 * are met:
36 * 1. Redistributions of source code must retain the above copyright
37 * notice, this list of conditions and the following disclaimer.
38 * 2. Redistributions in binary form must reproduce the above copyright
39 * notice, this list of conditions and the following disclaimer in the
40 * documentation and/or other materials provided with the distribution.
41 *
42 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
43 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
44 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
45 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
46 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
47 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
48 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
49 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
50 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
51 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
52 */
53
54
55#include <sys/cdefs.h>
56__KERNEL_RCSID(0, "$NetBSD: hypervisor.c,v 1.69 2016/07/11 11:31:50 msaitoh Exp $");
57
58#include <sys/param.h>
59#include <sys/systm.h>
60#include <sys/device.h>
61#include <sys/malloc.h>
62#include <sys/sysctl.h>
63
64#include "xenbus.h"
65#include "xencons.h"
66#include "isa.h"
67#include "pci.h"
68#include "acpica.h"
69
70#include "opt_xen.h"
71#include "opt_mpbios.h"
72
73#include <xen/xen.h>
74#include <xen/hypervisor.h>
75#include <xen/evtchn.h>
76#include <xen/xen-public/version.h>
77
78#include <sys/cpu.h>
79#include <sys/dirent.h>
80#include <sys/stat.h>
81#include <sys/tree.h>
82#include <sys/vnode.h>
83#include <miscfs/specfs/specdev.h>
84#include <miscfs/kernfs/kernfs.h>
85#include <xen/kernfs_machdep.h>
86#include <dev/isa/isavar.h>
87#include <xen/granttables.h>
88#include <xen/vcpuvar.h>
89#if NPCI > 0
90#include <dev/pci/pcivar.h>
91#if NACPICA > 0
92#include <dev/acpi/acpivar.h>
93#include <machine/mpconfig.h>
94#include <xen/mpacpi.h>
95#endif
96#ifdef MPBIOS
97#include <machine/mpbiosvar.h>
98#endif
99#endif /* NPCI */
100
101#if NXENBUS > 0
102#include <xen/xenbus.h>
103#endif
104
105#if NXENNET_HYPERVISOR > 0
106#include <net/if.h>
107#include <net/if_ether.h>
108#include <net/if_media.h>
109#include <xen/if_xennetvar.h>
110#endif
111
112#if NXBD_HYPERVISOR > 0
113#include <sys/buf.h>
114#include <sys/disk.h>
115#include <sys/bufq.h>
116#include <dev/dkvar.h>
117#include <xen/xbdvar.h>
118#endif
119
120int hypervisor_match(device_t, cfdata_t, void *);
121void hypervisor_attach(device_t, device_t, void *);
122
123CFATTACH_DECL_NEW(hypervisor, 0,
124 hypervisor_match, hypervisor_attach, NULL, NULL);
125
126static int hypervisor_print(void *, const char *);
127
128union hypervisor_attach_cookie {
129 const char *hac_device; /* first elem of all */
130#if NXENCONS > 0
131 struct xencons_attach_args hac_xencons;
132#endif
133#if NXENBUS > 0
134 struct xenbus_attach_args hac_xenbus;
135#endif
136#if NXENNET_HYPERVISOR > 0
137 struct xennet_attach_args hac_xennet;
138#endif
139#if NXBD_HYPERVISOR > 0
140 struct xbd_attach_args hac_xbd;
141#endif
142#if NPCI > 0
143 struct pcibus_attach_args hac_pba;
144#if defined(DOM0OPS) && NISA > 0
145 struct isabus_attach_args hac_iba;
146#endif
147#if NACPICA > 0
148 struct acpibus_attach_args hac_acpi;
149#endif
150#endif /* NPCI */
151 struct vcpu_attach_args hac_vcaa;
152};
153
154/*
155 * This is set when the ISA bus is attached. If it's not set by the
156 * time it's checked below, then mainbus attempts to attach an ISA.
157 */
158#ifdef DOM0OPS
159int isa_has_been_seen;
160#if NISA > 0
161struct x86_isa_chipset x86_isa_chipset;
162#endif
163#endif
164
165int xen_version;
166
167/* power management, for save/restore */
168static bool hypervisor_suspend(device_t, const pmf_qual_t *);
169static bool hypervisor_resume(device_t, const pmf_qual_t *);
170
171/*
172 * Probe for the hypervisor; always succeeds.
173 */
174int
175hypervisor_match(device_t parent, cfdata_t match, void *aux)
176{
177 struct hypervisor_attach_args *haa = aux;
178
179 if (strncmp(haa->haa_busname, "hypervisor", sizeof("hypervisor")) == 0)
180 return 1;
181 return 0;
182}
183
184#ifdef MULTIPROCESSOR
185static int
186hypervisor_vcpu_print(void *aux, const char *parent)
187{
188 /* Unconfigured cpus are ignored quietly. */
189 return (QUIET);
190}
191#endif /* MULTIPROCESSOR */
192
193/*
194 * Attach the hypervisor.
195 */
196void
197hypervisor_attach(device_t parent, device_t self, void *aux)
198{
199
200#if NPCI >0
201#ifdef PCI_BUS_FIXUP
202 int pci_maxbus = 0;
203#endif
204#endif /* NPCI */
205 union hypervisor_attach_cookie hac;
206 char xen_extra_version[XEN_EXTRAVERSION_LEN];
207 static char xen_version_string[20];
208 int rc;
209 const struct sysctlnode *node = NULL;
210
211 xenkernfs_init();
212
213 xen_version = HYPERVISOR_xen_version(XENVER_version, NULL);
214 memset(xen_extra_version, 0, sizeof(xen_extra_version));
215 HYPERVISOR_xen_version(XENVER_extraversion, xen_extra_version);
216 rc = snprintf(xen_version_string, 20, "%d.%d%s", XEN_MAJOR(xen_version),
217 XEN_MINOR(xen_version), xen_extra_version);
218 aprint_normal(": Xen version %s\n", xen_version_string);
219 if (rc >= 20)
220 aprint_debug(": xen_version_string truncated\n");
221
222 sysctl_createv(NULL, 0, NULL, &node, 0,
223 CTLTYPE_NODE, "xen",
224 SYSCTL_DESCR("Xen top level node"),
225 NULL, 0, NULL, 0, CTL_MACHDEP, CTL_CREATE, CTL_EOL);
226
227 if (node != NULL) {
228 sysctl_createv(NULL, 0, &node, NULL, CTLFLAG_READONLY,
229 CTLTYPE_STRING, "version",
230 SYSCTL_DESCR("Xen hypervisor version"),
231 NULL, 0, xen_version_string, 0, CTL_CREATE, CTL_EOL);
232 }
233
234 aprint_verbose_dev(self, "features: ");
235#define XEN_TST_F(n) \
236 if (xen_feature(XENFEAT_##n)) \
237 aprint_verbose(" %s", #n);
238
239 XEN_TST_F(writable_page_tables);
240 XEN_TST_F(writable_descriptor_tables);
241 XEN_TST_F(auto_translated_physmap);
242 XEN_TST_F(supervisor_mode_kernel);
243 XEN_TST_F(pae_pgdir_above_4gb);
244 XEN_TST_F(mmu_pt_update_preserve_ad);
245 XEN_TST_F(highmem_assist);
246 XEN_TST_F(gnttab_map_avail_bits);
247 XEN_TST_F(hvm_callback_vector);
248 XEN_TST_F(hvm_safe_pvclock);
249 XEN_TST_F(hvm_pirqs);
250#undef XEN_TST_F
251 aprint_verbose("\n");
252
253 xengnt_init();
254 events_init();
255
256 memset(&hac, 0, sizeof(hac));
257 hac.hac_vcaa.vcaa_name = "vcpu";
258 hac.hac_vcaa.vcaa_caa.cpu_number = 0;
259 hac.hac_vcaa.vcaa_caa.cpu_role = CPU_ROLE_BP;
260 hac.hac_vcaa.vcaa_caa.cpu_func = NULL; /* See xen/x86/cpu.c:vcpu_attach() */
261 config_found_ia(self, "xendevbus", &hac.hac_vcaa, hypervisor_print);
262
263#ifdef MULTIPROCESSOR
264
265 /*
266 * The xenstore contains the configured number of vcpus.
267 * The xenstore however, is not accessible until much later in
268 * the boot sequence. We therefore bruteforce check for
269 * allocated vcpus (See: cpu.c:vcpu_match()) by iterating
270 * through the maximum supported by NetBSD MP.
271 */
272 cpuid_t vcpuid;
273
274 for (vcpuid = 1; vcpuid < maxcpus; vcpuid++) {
275 memset(&hac, 0, sizeof(hac));
276 hac.hac_vcaa.vcaa_name = "vcpu";
277 hac.hac_vcaa.vcaa_caa.cpu_number = vcpuid;
278 hac.hac_vcaa.vcaa_caa.cpu_role = CPU_ROLE_AP;
279 hac.hac_vcaa.vcaa_caa.cpu_func = NULL; /* See xen/x86/cpu.c:vcpu_attach() */
280 if (NULL == config_found_ia(self, "xendevbus", &hac.hac_vcaa,
281 hypervisor_vcpu_print)) {
282 break;
283 }
284 }
285
286#endif /* MULTIPROCESSOR */
287
288#if NXENBUS > 0
289 memset(&hac, 0, sizeof(hac));
290 hac.hac_xenbus.xa_device = "xenbus";
291 config_found_ia(self, "xendevbus", &hac.hac_xenbus, hypervisor_print);
292#endif
293#if NXENCONS > 0
294 memset(&hac, 0, sizeof(hac));
295 hac.hac_xencons.xa_device = "xencons";
296 config_found_ia(self, "xendevbus", &hac.hac_xencons, hypervisor_print);
297#endif
298#ifdef DOM0OPS
299#if NPCI > 0
300#if NACPICA > 0
301 if (acpi_present) {
302 memset(&hac, 0, sizeof(hac));
303 hac.hac_acpi.aa_iot = x86_bus_space_io;
304 hac.hac_acpi.aa_memt = x86_bus_space_mem;
305 hac.hac_acpi.aa_pc = NULL;
306 hac.hac_acpi.aa_pciflags =
307 PCI_FLAGS_IO_OKAY | PCI_FLAGS_MEM_OKAY |
308 PCI_FLAGS_MRL_OKAY | PCI_FLAGS_MRM_OKAY |
309 PCI_FLAGS_MWI_OKAY;
310 hac.hac_acpi.aa_ic = &x86_isa_chipset;
311 hac.hac_acpi.aa_dmat = &pci_bus_dma_tag;
312#ifdef _LP64
313 hac.hac_acpi.aa_dmat64 = &pci_bus_dma64_tag;
314#else
315 hac.hac_acpi.aa_dmat64 = NULL;
316#endif /* _LP64 */
317 config_found_ia(self, "acpibus", &hac.hac_acpi, 0);
318 }
319#endif /* NACPICA */
320 memset(&hac, 0, sizeof(hac));
321 hac.hac_pba.pba_iot = x86_bus_space_io;
322 hac.hac_pba.pba_memt = x86_bus_space_mem;
323 hac.hac_pba.pba_dmat = &pci_bus_dma_tag;
324#ifdef _LP64
325 hac.hac_pba.pba_dmat64 = &pci_bus_dma64_tag;
326#else
327 hac.hac_pba.pba_dmat64 = NULL;
328#endif /* _LP64 */
329 hac.hac_pba.pba_flags = PCI_FLAGS_MEM_OKAY | PCI_FLAGS_IO_OKAY;
330 hac.hac_pba.pba_bridgetag = NULL;
331 hac.hac_pba.pba_bus = 0;
332#if NACPICA > 0 && defined(ACPI_SCANPCI)
333 if (mpacpi_active)
334 mp_pci_scan(self, &hac.hac_pba, pcibusprint);
335 else
336#endif
337#if defined(MPBIOS) && defined(MPBIOS_SCANPCI)
338 if (mpbios_scanned != 0)
339 mp_pci_scan(self, &hac.hac_pba, pcibusprint);
340 else
341#endif
342 config_found_ia(self, "pcibus", &hac.hac_pba, pcibusprint);
343#if NACPICA > 0
344 if (mp_verbose)
345 acpi_pci_link_state();
346#endif
347#if NISA > 0
348 if (isa_has_been_seen == 0) {
349 memset(&hac, 0, sizeof(hac));
350 hac.hac_iba._iba_busname = "isa";
351 hac.hac_iba.iba_iot = x86_bus_space_io;
352 hac.hac_iba.iba_memt = x86_bus_space_mem;
353 hac.hac_iba.iba_dmat = &isa_bus_dma_tag;
354 hac.hac_iba.iba_ic = NULL; /* No isa DMA yet */
355 config_found_ia(self, "isabus", &hac.hac_iba, isabusprint);
356 }
357#endif /* NISA */
358#endif /* NPCI */
359
360 if (xendomain_is_privileged()) {
361 xenprivcmd_init();
362 xen_shm_init();
363 }
364#endif /* DOM0OPS */
365
366 hypervisor_machdep_attach();
367
368 if (!pmf_device_register(self, hypervisor_suspend, hypervisor_resume))
369 aprint_error_dev(self, "couldn't establish power handler\n");
370
371}
372
373static bool
374hypervisor_suspend(device_t dev, const pmf_qual_t *qual)
375{
376 events_suspend();
377 xengnt_suspend();
378
379 return true;
380}
381
382static bool
383hypervisor_resume(device_t dev, const pmf_qual_t *qual)
384{
385 hypervisor_machdep_resume();
386
387 xengnt_resume();
388 events_resume();
389
390 return true;
391}
392
393static int
394hypervisor_print(void *aux, const char *parent)
395{
396 union hypervisor_attach_cookie *hac = aux;
397
398 if (parent)
399 aprint_normal("%s at %s", hac->hac_device, parent);
400 return (UNCONF);
401}
402
403#define DIR_MODE (S_IRUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH)
404
405kernfs_parentdir_t *kernxen_pkt;
406
407void
408xenkernfs_init(void)
409{
410 kernfs_entry_t *dkt;
411
412 KERNFS_ALLOCENTRY(dkt, M_TEMP, M_WAITOK);
413 KERNFS_INITENTRY(dkt, DT_DIR, "xen", NULL, KFSsubdir, VDIR, DIR_MODE);
414 kernfs_addentry(NULL, dkt);
415 kernxen_pkt = KERNFS_ENTOPARENTDIR(dkt);
416}
417