1 /* 2 * Copyright (c) 2008 Citrix Systems, Inc. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 */ 26 27 #include <sys/cdefs.h> 28 __FBSDID("$FreeBSD$"); 29 30 #include <sys/param.h> 31 #include <sys/bus.h> 32 #include <sys/kernel.h> 33 #include <sys/malloc.h> 34 #include <sys/module.h> 35 #include <sys/proc.h> 36 #include <sys/systm.h> 37 #include <sys/time.h> 38 39 #include <machine/bus.h> 40 #include <machine/resource.h> 41 #include <sys/rman.h> 42 43 #include <machine/stdarg.h> 44 #include <machine/xen/xen-os.h> 45 #include <xen/features.h> 46 #include <xen/hypervisor.h> 47 #include <xen/gnttab.h> 48 #include <xen/xen_intr.h> 49 #include <xen/interface/memory.h> 50 #include <xen/interface/hvm/params.h> 51 52 #include <dev/pci/pcireg.h> 53 #include <dev/pci/pcivar.h> 54 55 #include <vm/vm.h> 56 #include <vm/vm_extern.h> 57 #include <vm/vm_kern.h> 58 #include <vm/pmap.h> 59 60 #include <dev/xen/xenpci/xenpcivar.h> 61 62 /* 63 * These variables are used by the rest of the kernel to access the 64 * hypervisor. 65 */ 66 char *hypercall_stubs; 67 shared_info_t *HYPERVISOR_shared_info; 68 static vm_paddr_t shared_info_pa; 69 static device_t nexus; 70 71 /* 72 * This is used to find our platform device instance. 73 */ 74 static devclass_t xenpci_devclass; 75 76 /* 77 * Return the CPUID base address for Xen functions. 78 */ 79 static uint32_t 80 xenpci_cpuid_base(void) 81 { 82 uint32_t base, regs[4]; 83 84 for (base = 0x40000000; base < 0x40010000; base += 0x100) { 85 do_cpuid(base, regs); 86 if (!memcmp("XenVMMXenVMM", ®s[1], 12) 87 && (regs[0] - base) >= 2) 88 return (base); 89 } 90 return (0); 91 } 92 93 /* 94 * Allocate and fill in the hypcall page. 95 */ 96 static int 97 xenpci_init_hypercall_stubs(device_t dev, struct xenpci_softc * scp) 98 { 99 uint32_t base, regs[4]; 100 int i; 101 102 base = xenpci_cpuid_base(); 103 if (!base) { 104 device_printf(dev, "Xen platform device but not Xen VMM\n"); 105 return (EINVAL); 106 } 107 108 if (bootverbose) { 109 do_cpuid(base + 1, regs); 110 device_printf(dev, "Xen version %d.%d.\n", 111 regs[0] >> 16, regs[0] & 0xffff); 112 } 113 114 /* 115 * Find the hypercall pages. 116 */ 117 do_cpuid(base + 2, regs); 118 119 hypercall_stubs = malloc(regs[0] * PAGE_SIZE, M_TEMP, M_WAITOK); 120 121 for (i = 0; i < regs[0]; i++) { 122 wrmsr(regs[1], vtophys(hypercall_stubs + i * PAGE_SIZE) + i); 123 } 124 125 return (0); 126 } 127 128 /* 129 * After a resume, re-initialise the hypercall page. 130 */ 131 static void 132 xenpci_resume_hypercall_stubs(device_t dev, struct xenpci_softc * scp) 133 { 134 uint32_t base, regs[4]; 135 int i; 136 137 base = xenpci_cpuid_base(); 138 139 do_cpuid(base + 2, regs); 140 for (i = 0; i < regs[0]; i++) { 141 wrmsr(regs[1], vtophys(hypercall_stubs + i * PAGE_SIZE) + i); 142 } 143 } 144 145 /* 146 * Tell the hypervisor how to contact us for event channel callbacks. 147 */ 148 static void 149 xenpci_set_callback(device_t dev) 150 { 151 int irq; 152 uint64_t callback; 153 struct xen_hvm_param xhp; 154 155 irq = pci_get_irq(dev); 156 if (irq < 16) { 157 callback = irq; 158 } else { 159 callback = (pci_get_intpin(dev) - 1) & 3; 160 callback |= pci_get_slot(dev) << 11; 161 callback |= 1ull << 56; 162 } 163 164 xhp.domid = DOMID_SELF; 165 xhp.index = HVM_PARAM_CALLBACK_IRQ; 166 xhp.value = callback; 167 if (HYPERVISOR_hvm_op(HVMOP_set_param, &xhp)) 168 panic("Can't set evtchn callback"); 169 } 170 171 172 /* 173 * Deallocate anything allocated by xenpci_allocate_resources. 174 */ 175 static int 176 xenpci_deallocate_resources(device_t dev) 177 { 178 struct xenpci_softc *scp = device_get_softc(dev); 179 180 if (scp->res_irq != 0) { 181 bus_deactivate_resource(dev, SYS_RES_IRQ, 182 scp->rid_irq, scp->res_irq); 183 bus_release_resource(dev, SYS_RES_IRQ, 184 scp->rid_irq, scp->res_irq); 185 scp->res_irq = 0; 186 } 187 if (scp->res_memory != 0) { 188 bus_deactivate_resource(dev, SYS_RES_MEMORY, 189 scp->rid_memory, scp->res_memory); 190 bus_release_resource(dev, SYS_RES_MEMORY, 191 scp->rid_memory, scp->res_memory); 192 scp->res_memory = 0; 193 } 194 195 return (0); 196 } 197 198 /* 199 * Allocate irq and memory resources. 200 */ 201 static int 202 xenpci_allocate_resources(device_t dev) 203 { 204 struct xenpci_softc *scp = device_get_softc(dev); 205 206 scp->res_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, 207 &scp->rid_irq, RF_SHAREABLE|RF_ACTIVE); 208 if (scp->res_irq == NULL) { 209 printf("xenpci Could not allocate irq.\n"); 210 goto errexit; 211 } 212 213 scp->rid_memory = PCIR_BAR(1); 214 scp->res_memory = bus_alloc_resource_any(dev, SYS_RES_MEMORY, 215 &scp->rid_memory, RF_ACTIVE); 216 if (scp->res_memory == NULL) { 217 printf("xenpci Could not allocate memory bar.\n"); 218 goto errexit; 219 } 220 221 scp->phys_next = rman_get_start(scp->res_memory); 222 223 return (0); 224 225 errexit: 226 /* Cleanup anything we may have assigned. */ 227 xenpci_deallocate_resources(dev); 228 return (ENXIO); /* For want of a better idea. */ 229 } 230 231 /* 232 * Allocate a physical address range from our mmio region. 233 */ 234 static int 235 xenpci_alloc_space_int(struct xenpci_softc *scp, size_t sz, 236 vm_paddr_t *pa) 237 { 238 239 if (scp->phys_next + sz > rman_get_end(scp->res_memory)) { 240 return (ENOMEM); 241 } 242 243 *pa = scp->phys_next; 244 scp->phys_next += sz; 245 246 return (0); 247 } 248 249 /* 250 * Allocate a physical address range from our mmio region. 251 */ 252 int 253 xenpci_alloc_space(size_t sz, vm_paddr_t *pa) 254 { 255 device_t dev = devclass_get_device(xenpci_devclass, 0); 256 257 if (dev) { 258 return (xenpci_alloc_space_int(device_get_softc(dev), 259 sz, pa)); 260 } else { 261 return (ENOMEM); 262 } 263 } 264 265 static struct resource * 266 xenpci_alloc_resource(device_t dev, device_t child, int type, int *rid, 267 u_long start, u_long end, u_long count, u_int flags) 268 { 269 return (BUS_ALLOC_RESOURCE(nexus, child, type, rid, start, 270 end, count, flags)); 271 } 272 273 274 static int 275 xenpci_release_resource(device_t dev, device_t child, int type, int rid, 276 struct resource *r) 277 { 278 return (BUS_RELEASE_RESOURCE(nexus, child, type, rid, r)); 279 } 280 281 static int 282 xenpci_activate_resource(device_t dev, device_t child, int type, int rid, 283 struct resource *r) 284 { 285 return (BUS_ACTIVATE_RESOURCE(nexus, child, type, rid, r)); 286 } 287 288 static int 289 xenpci_deactivate_resource(device_t dev, device_t child, int type, 290 int rid, struct resource *r) 291 { 292 return (BUS_DEACTIVATE_RESOURCE(nexus, child, type, rid, r)); 293 } 294 295 /* 296 * Called very early in the resume sequence - reinitialise the various 297 * bits of Xen machinery including the hypercall page and the shared 298 * info page. 299 */ 300 void 301 xenpci_resume() 302 { 303 device_t dev = devclass_get_device(xenpci_devclass, 0); 304 struct xenpci_softc *scp = device_get_softc(dev); 305 struct xen_add_to_physmap xatp; 306 307 xenpci_resume_hypercall_stubs(dev, scp); 308 309 xatp.domid = DOMID_SELF; 310 xatp.idx = 0; 311 xatp.space = XENMAPSPACE_shared_info; 312 xatp.gpfn = shared_info_pa >> PAGE_SHIFT; 313 if (HYPERVISOR_memory_op(XENMEM_add_to_physmap, &xatp)) 314 panic("HYPERVISOR_memory_op failed"); 315 316 pmap_kenter((vm_offset_t) HYPERVISOR_shared_info, shared_info_pa); 317 318 xenpci_set_callback(dev); 319 320 gnttab_resume(); 321 irq_resume(); 322 } 323 324 /* 325 * Probe - just check device ID. 326 */ 327 static int 328 xenpci_probe(device_t dev) 329 { 330 331 if (pci_get_devid(dev) != 0x00015853) 332 return (ENXIO); 333 334 device_set_desc(dev, "Xen Platform Device"); 335 return (bus_generic_probe(dev)); 336 } 337 338 /* 339 * Attach - find resources and talk to Xen. 340 */ 341 static int 342 xenpci_attach(device_t dev) 343 { 344 int error; 345 struct xenpci_softc *scp = device_get_softc(dev); 346 struct xen_add_to_physmap xatp; 347 vm_offset_t shared_va; 348 devclass_t dc; 349 350 /* 351 * Find and record nexus0. Since we are not really on the 352 * PCI bus, all resource operations are directed to nexus 353 * instead of through our parent. 354 */ 355 if ((dc = devclass_find("nexus")) == 0 356 || (nexus = devclass_get_device(dc, 0)) == 0) { 357 device_printf(dev, "unable to find nexus."); 358 return (ENOENT); 359 } 360 361 error = xenpci_allocate_resources(dev); 362 if (error) { 363 device_printf(dev, "xenpci_allocate_resources failed(%d).\n", 364 error); 365 goto errexit; 366 } 367 368 error = xenpci_init_hypercall_stubs(dev, scp); 369 if (error) { 370 device_printf(dev, "xenpci_init_hypercall_stubs failed(%d).\n", 371 error); 372 goto errexit; 373 } 374 375 setup_xen_features(); 376 377 xenpci_alloc_space_int(scp, PAGE_SIZE, &shared_info_pa); 378 379 xatp.domid = DOMID_SELF; 380 xatp.idx = 0; 381 xatp.space = XENMAPSPACE_shared_info; 382 xatp.gpfn = shared_info_pa >> PAGE_SHIFT; 383 if (HYPERVISOR_memory_op(XENMEM_add_to_physmap, &xatp)) 384 panic("HYPERVISOR_memory_op failed"); 385 386 shared_va = kmem_alloc_nofault(kernel_map, PAGE_SIZE); 387 pmap_kenter(shared_va, shared_info_pa); 388 HYPERVISOR_shared_info = (void *) shared_va; 389 390 /* 391 * Hook the irq up to evtchn 392 */ 393 xenpci_irq_init(dev, scp); 394 xenpci_set_callback(dev); 395 396 return (bus_generic_attach(dev)); 397 398 errexit: 399 /* 400 * Undo anything we may have done. 401 */ 402 xenpci_deallocate_resources(dev); 403 return (error); 404 } 405 406 /* 407 * Detach - reverse anything done by attach. 408 */ 409 static int 410 xenpci_detach(device_t dev) 411 { 412 struct xenpci_softc *scp = device_get_softc(dev); 413 device_t parent = device_get_parent(dev); 414 415 /* 416 * Take our interrupt handler out of the list of handlers 417 * that can handle this irq. 418 */ 419 if (scp->intr_cookie != NULL) { 420 if (BUS_TEARDOWN_INTR(parent, dev, 421 scp->res_irq, scp->intr_cookie) != 0) 422 device_printf(dev, 423 "intr teardown failed.. continuing\n"); 424 scp->intr_cookie = NULL; 425 } 426 427 /* 428 * Deallocate any system resources we may have 429 * allocated on behalf of this driver. 430 */ 431 return (xenpci_deallocate_resources(dev)); 432 } 433 434 static device_method_t xenpci_methods[] = { 435 /* Device interface */ 436 DEVMETHOD(device_probe, xenpci_probe), 437 DEVMETHOD(device_attach, xenpci_attach), 438 DEVMETHOD(device_detach, xenpci_detach), 439 DEVMETHOD(device_suspend, bus_generic_suspend), 440 DEVMETHOD(device_resume, bus_generic_resume), 441 442 /* Bus interface */ 443 DEVMETHOD(bus_add_child, bus_generic_add_child), 444 DEVMETHOD(bus_alloc_resource, xenpci_alloc_resource), 445 DEVMETHOD(bus_release_resource, xenpci_release_resource), 446 DEVMETHOD(bus_activate_resource, xenpci_activate_resource), 447 DEVMETHOD(bus_deactivate_resource, xenpci_deactivate_resource), 448 449 { 0, 0 } 450 }; 451 452 static driver_t xenpci_driver = { 453 "xenpci", 454 xenpci_methods, 455 sizeof(struct xenpci_softc), 456 }; 457 458 DRIVER_MODULE(xenpci, pci, xenpci_driver, xenpci_devclass, 0, 0); 459