1 /* $NetBSD: viomb.c,v 1.5 2015/10/27 16:04:19 christos Exp $ */ 2 3 /* 4 * Copyright (c) 2010 Minoura Makoto. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 21 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 25 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 */ 27 28 #include <sys/cdefs.h> 29 __KERNEL_RCSID(0, "$NetBSD: viomb.c,v 1.5 2015/10/27 16:04:19 christos Exp $"); 30 31 #include <sys/param.h> 32 #include <sys/systm.h> 33 #include <sys/kernel.h> 34 #include <sys/bus.h> 35 #include <sys/condvar.h> 36 #include <sys/device.h> 37 #include <sys/kthread.h> 38 #include <sys/mutex.h> 39 #include <sys/sysctl.h> 40 #include <uvm/uvm_page.h> 41 42 #include <dev/pci/pcidevs.h> 43 #include <dev/pci/pcireg.h> 44 #include <dev/pci/pcivar.h> 45 46 #include <dev/pci/virtioreg.h> 47 #include <dev/pci/virtiovar.h> 48 49 /* Configuration registers */ 50 #define VIRTIO_BALLOON_CONFIG_NUM_PAGES 0 /* 32bit */ 51 #define VIRTIO_BALLOON_CONFIG_ACTUAL 4 /* 32bit */ 52 53 /* Feature bits */ 54 #define VIRTIO_BALLOON_F_MUST_TELL_HOST (1<<0) 55 #define VIRTIO_BALLOON_F_STATS_VQ (1<<1) 56 57 #define VIRTIO_BALLOON_FLAG_BITS \ 58 VIRTIO_COMMON_FLAG_BITS \ 59 "\x02""STATS_VQ" \ 60 "\x01""MUST_TELL_HOST" 61 62 #define PGS_PER_REQ (256) /* 1MB, 4KB/page */ 63 64 CTASSERT((PAGE_SIZE) == (VIRTIO_PAGE_SIZE)); /* XXX */ 65 66 struct balloon_req { 67 bus_dmamap_t bl_dmamap; 68 struct pglist bl_pglist; 69 int bl_nentries; 70 uint32_t bl_pages[PGS_PER_REQ]; 71 }; 72 73 struct viomb_softc { 74 device_t sc_dev; 75 76 struct virtio_softc *sc_virtio; 77 struct virtqueue sc_vq[2]; 78 79 unsigned int sc_npages; 80 unsigned int sc_actual; 81 int sc_inflight; 82 struct balloon_req sc_req; 83 struct pglist sc_balloon_pages; 84 85 int sc_inflate_done; 86 int sc_deflate_done; 87 88 kcondvar_t sc_wait; 89 kmutex_t sc_waitlock; 90 }; 91 92 static int balloon_initialized = 0; /* multiple balloon is not allowed */ 93 94 static int viomb_match(device_t, cfdata_t, void *); 95 static void viomb_attach(device_t, device_t, void *); 96 static void viomb_read_config(struct viomb_softc *); 97 static int viomb_config_change(struct virtio_softc *); 98 static int inflate(struct viomb_softc *); 99 static int inflateq_done(struct virtqueue *); 100 static int inflate_done(struct viomb_softc *); 101 static int deflate(struct viomb_softc *); 102 static int deflateq_done(struct virtqueue *); 103 static int deflate_done(struct viomb_softc *); 104 static void viomb_thread(void *); 105 106 CFATTACH_DECL_NEW(viomb, sizeof(struct viomb_softc), 107 viomb_match, viomb_attach, NULL, NULL); 108 109 static int 110 viomb_match(device_t parent, cfdata_t match, void *aux) 111 { 112 struct virtio_softc *vsc = aux; 113 114 if (vsc->sc_childdevid == PCI_PRODUCT_VIRTIO_BALLOON) 115 return 1; 116 117 return 0; 118 } 119 120 static void 121 viomb_attach(device_t parent, device_t self, void *aux) 122 { 123 struct viomb_softc *sc = device_private(self); 124 struct virtio_softc *vsc = device_private(parent); 125 const struct sysctlnode *node; 126 uint32_t features; 127 char buf[256]; 128 129 if (vsc->sc_child != NULL) { 130 aprint_normal(": child already attached for %s; " 131 "something wrong...\n", 132 device_xname(parent)); 133 return; 134 } 135 if (balloon_initialized++) { 136 aprint_normal(": balloon already exists; something wrong...\n"); 137 goto err_none; 138 } 139 140 sc->sc_dev = self; 141 sc->sc_virtio = vsc; 142 143 vsc->sc_child = self; 144 vsc->sc_ipl = IPL_VM; 145 vsc->sc_vqs = &sc->sc_vq[0]; 146 vsc->sc_nvqs = 2; 147 vsc->sc_config_change = viomb_config_change; 148 vsc->sc_intrhand = virtio_vq_intr; 149 vsc->sc_flags = 0; 150 151 features = virtio_negotiate_features(vsc, 152 VIRTIO_CONFIG_DEVICE_FEATURES); 153 154 snprintb(buf, sizeof(buf), VIRTIO_BALLOON_FLAG_BITS, features); 155 aprint_normal(": Features: %s\n", buf); 156 if ((virtio_alloc_vq(vsc, &sc->sc_vq[0], 0, 157 sizeof(uint32_t)*PGS_PER_REQ, 1, 158 "inflate") != 0) || 159 (virtio_alloc_vq(vsc, &sc->sc_vq[1], 1, 160 sizeof(uint32_t)*PGS_PER_REQ, 1, 161 "deflate") != 0)) { 162 goto err_none; 163 } 164 sc->sc_vq[0].vq_done = inflateq_done; 165 sc->sc_vq[1].vq_done = deflateq_done; 166 167 viomb_read_config(sc); 168 sc->sc_inflight = 0; 169 TAILQ_INIT(&sc->sc_balloon_pages); 170 171 if (bus_dmamap_create(vsc->sc_dmat, sizeof(uint32_t)*PGS_PER_REQ, 172 1, sizeof(uint32_t)*PGS_PER_REQ, 0, 173 BUS_DMA_NOWAIT, &sc->sc_req.bl_dmamap)) { 174 aprint_error_dev(sc->sc_dev, "dmamap creation failed.\n"); 175 goto err_vq; 176 } 177 if (bus_dmamap_load(vsc->sc_dmat, sc->sc_req.bl_dmamap, 178 &sc->sc_req.bl_pages[0], 179 sizeof(uint32_t) * PGS_PER_REQ, 180 NULL, BUS_DMA_NOWAIT)) { 181 aprint_error_dev(sc->sc_dev, "dmamap load failed.\n"); 182 goto err_dmamap; 183 } 184 185 sc->sc_inflate_done = sc->sc_deflate_done = 0; 186 mutex_init(&sc->sc_waitlock, MUTEX_DEFAULT, IPL_VM); /* spin */ 187 cv_init(&sc->sc_wait, "balloon"); 188 189 if (kthread_create(PRI_IDLE, KTHREAD_MPSAFE, NULL, 190 viomb_thread, sc, NULL, "viomb")) { 191 aprint_error_dev(sc->sc_dev, "cannot create kthread.\n"); 192 goto err_mutex; 193 } 194 195 sysctl_createv(NULL, 0, NULL, &node, 0, CTLTYPE_NODE, 196 "viomb", SYSCTL_DESCR("VirtIO Balloon status"), 197 NULL, 0, NULL, 0, 198 CTL_HW, CTL_CREATE, CTL_EOL); 199 sysctl_createv(NULL, 0, NULL, NULL, 0, CTLTYPE_INT, 200 "npages", SYSCTL_DESCR("VirtIO Balloon npages value"), 201 NULL, 0, &sc->sc_npages, 0, 202 CTL_HW, node->sysctl_num, CTL_CREATE, CTL_EOL); 203 sysctl_createv(NULL, 0, NULL, NULL, 0, CTLTYPE_INT, 204 "actual", SYSCTL_DESCR("VirtIO Balloon actual value"), 205 NULL, 0, &sc->sc_actual, 0, 206 CTL_HW, node->sysctl_num, CTL_CREATE, CTL_EOL); 207 return; 208 209 err_mutex: 210 cv_destroy(&sc->sc_wait); 211 mutex_destroy(&sc->sc_waitlock); 212 err_dmamap: 213 bus_dmamap_destroy(vsc->sc_dmat, sc->sc_req.bl_dmamap); 214 err_vq: 215 virtio_free_vq(vsc, &sc->sc_vq[1]); 216 virtio_free_vq(vsc, &sc->sc_vq[0]); 217 err_none: 218 vsc->sc_child = (void*)1; 219 return; 220 } 221 222 static void 223 viomb_read_config(struct viomb_softc *sc) 224 { 225 unsigned int reg; 226 227 /* these values are explicitly specified as little-endian */ 228 reg = virtio_read_device_config_4(sc->sc_virtio, 229 VIRTIO_BALLOON_CONFIG_NUM_PAGES); 230 sc->sc_npages = le32toh(reg); 231 232 reg = virtio_read_device_config_4(sc->sc_virtio, 233 VIRTIO_BALLOON_CONFIG_ACTUAL); 234 sc->sc_actual = le32toh(reg); 235 } 236 237 /* 238 * Config change callback: wakeup the kthread. 239 */ 240 static int 241 viomb_config_change(struct virtio_softc *vsc) 242 { 243 struct viomb_softc *sc = device_private(vsc->sc_child); 244 unsigned int old; 245 246 old = sc->sc_npages; 247 viomb_read_config(sc); 248 mutex_enter(&sc->sc_waitlock); 249 cv_signal(&sc->sc_wait); 250 mutex_exit(&sc->sc_waitlock); 251 if (sc->sc_npages > old) 252 printf("%s: inflating balloon from %u to %u.\n", 253 device_xname(sc->sc_dev), old, sc->sc_npages); 254 else if (sc->sc_npages < old) 255 printf("%s: deflating balloon from %u to %u.\n", 256 device_xname(sc->sc_dev), old, sc->sc_npages); 257 258 return 1; 259 } 260 261 /* 262 * Inflate: consume some amount of physical memory. 263 */ 264 static int 265 inflate(struct viomb_softc *sc) 266 { 267 struct virtio_softc *vsc = sc->sc_virtio; 268 int i, slot; 269 uint64_t nvpages, nhpages; 270 struct balloon_req *b; 271 struct vm_page *p; 272 struct virtqueue *vq = &sc->sc_vq[0]; 273 274 if (sc->sc_inflight) 275 return 0; 276 nvpages = sc->sc_npages - sc->sc_actual; 277 if (nvpages > PGS_PER_REQ) 278 nvpages = PGS_PER_REQ; 279 nhpages = nvpages * VIRTIO_PAGE_SIZE / PAGE_SIZE; 280 281 b = &sc->sc_req; 282 if (uvm_pglistalloc(nhpages*PAGE_SIZE, 0, UINT32_MAX*PAGE_SIZE, 283 0, 0, &b->bl_pglist, nhpages, 1)) { 284 printf("%s: %" PRIu64 " pages of physical memory " 285 "could not be allocated, retrying...\n", 286 device_xname(sc->sc_dev), nhpages); 287 return 1; /* sleep longer */ 288 } 289 290 b->bl_nentries = nvpages; 291 i = 0; 292 TAILQ_FOREACH(p, &b->bl_pglist, pageq.queue) { 293 b->bl_pages[i++] = p->phys_addr / VIRTIO_PAGE_SIZE; 294 } 295 KASSERT(i == nvpages); 296 297 if (virtio_enqueue_prep(vsc, vq, &slot) != 0) { 298 printf("%s: inflate enqueue failed.\n", 299 device_xname(sc->sc_dev)); 300 uvm_pglistfree(&b->bl_pglist); 301 return 0; 302 } 303 if (virtio_enqueue_reserve(vsc, vq, slot, 1)) { 304 printf("%s: inflate enqueue failed.\n", 305 device_xname(sc->sc_dev)); 306 uvm_pglistfree(&b->bl_pglist); 307 return 0; 308 } 309 bus_dmamap_sync(vsc->sc_dmat, b->bl_dmamap, 0, sizeof(uint32_t)*nvpages, 310 BUS_DMASYNC_PREWRITE); 311 virtio_enqueue(vsc, vq, slot, b->bl_dmamap, true); 312 virtio_enqueue_commit(vsc, vq, slot, true); 313 sc->sc_inflight += nvpages; 314 315 return 0; 316 } 317 318 static int 319 inflateq_done(struct virtqueue *vq) 320 { 321 struct virtio_softc *vsc = vq->vq_owner; 322 struct viomb_softc *sc = device_private(vsc->sc_child); 323 324 mutex_enter(&sc->sc_waitlock); 325 sc->sc_inflate_done = 1; 326 cv_signal(&sc->sc_wait); 327 mutex_exit(&sc->sc_waitlock); 328 329 return 1; 330 } 331 332 static int 333 inflate_done(struct viomb_softc *sc) 334 { 335 struct virtio_softc *vsc = sc->sc_virtio; 336 struct virtqueue *vq = &sc->sc_vq[0]; 337 struct balloon_req *b; 338 int r, slot; 339 uint64_t nvpages; 340 struct vm_page *p; 341 342 r = virtio_dequeue(vsc, vq, &slot, NULL); 343 if (r != 0) { 344 printf("%s: inflate dequeue failed, errno %d.\n", 345 device_xname(sc->sc_dev), r); 346 return 1; 347 } 348 virtio_dequeue_commit(vsc, vq, slot); 349 350 b = &sc->sc_req; 351 nvpages = b->bl_nentries; 352 bus_dmamap_sync(vsc->sc_dmat, b->bl_dmamap, 353 offsetof(struct balloon_req, bl_pages), 354 sizeof(uint32_t)*nvpages, 355 BUS_DMASYNC_POSTWRITE); 356 while (!TAILQ_EMPTY(&b->bl_pglist)) { 357 p = TAILQ_FIRST(&b->bl_pglist); 358 TAILQ_REMOVE(&b->bl_pglist, p, pageq.queue); 359 TAILQ_INSERT_TAIL(&sc->sc_balloon_pages, p, pageq.queue); 360 } 361 362 sc->sc_inflight -= nvpages; 363 virtio_write_device_config_4(vsc, 364 VIRTIO_BALLOON_CONFIG_ACTUAL, 365 sc->sc_actual + nvpages); 366 viomb_read_config(sc); 367 368 return 1; 369 } 370 371 /* 372 * Deflate: free previously allocated memory. 373 */ 374 static int 375 deflate(struct viomb_softc *sc) 376 { 377 struct virtio_softc *vsc = sc->sc_virtio; 378 int i, slot; 379 uint64_t nvpages, nhpages; 380 struct balloon_req *b; 381 struct vm_page *p; 382 struct virtqueue *vq = &sc->sc_vq[1]; 383 384 nvpages = (sc->sc_actual + sc->sc_inflight) - sc->sc_npages; 385 if (nvpages > PGS_PER_REQ) 386 nvpages = PGS_PER_REQ; 387 nhpages = nvpages * VIRTIO_PAGE_SIZE / PAGE_SIZE; 388 389 b = &sc->sc_req; 390 391 b->bl_nentries = nvpages; 392 TAILQ_INIT(&b->bl_pglist); 393 for (i = 0; i < nhpages; i++) { 394 p = TAILQ_FIRST(&sc->sc_balloon_pages); 395 if (p == NULL) 396 break; 397 TAILQ_REMOVE(&sc->sc_balloon_pages, p, pageq.queue); 398 TAILQ_INSERT_TAIL(&b->bl_pglist, p, pageq.queue); 399 b->bl_pages[i] = p->phys_addr / VIRTIO_PAGE_SIZE; 400 } 401 402 if (virtio_enqueue_prep(vsc, vq, &slot) != 0) { 403 printf("%s: deflate enqueue failed.\n", 404 device_xname(sc->sc_dev)); 405 TAILQ_FOREACH_REVERSE(p, &b->bl_pglist, pglist, pageq.queue) { 406 TAILQ_REMOVE(&b->bl_pglist, p, pageq.queue); 407 TAILQ_INSERT_HEAD(&sc->sc_balloon_pages, p, pageq.queue); 408 } 409 return 0; 410 } 411 if (virtio_enqueue_reserve(vsc, vq, slot, 1) != 0) { 412 printf("%s: deflate enqueue failed.\n", 413 device_xname(sc->sc_dev)); 414 TAILQ_FOREACH_REVERSE(p, &b->bl_pglist, pglist, pageq.queue) { 415 TAILQ_REMOVE(&b->bl_pglist, p, pageq.queue); 416 TAILQ_INSERT_HEAD(&sc->sc_balloon_pages, p, pageq.queue); 417 } 418 return 0; 419 } 420 bus_dmamap_sync(vsc->sc_dmat, b->bl_dmamap, 0, sizeof(uint32_t)*nvpages, 421 BUS_DMASYNC_PREWRITE); 422 virtio_enqueue(vsc, vq, slot, b->bl_dmamap, true); 423 virtio_enqueue_commit(vsc, vq, slot, true); 424 sc->sc_inflight -= nvpages; 425 426 if (!(vsc->sc_features & VIRTIO_BALLOON_F_MUST_TELL_HOST)) 427 uvm_pglistfree(&b->bl_pglist); 428 429 return 0; 430 } 431 432 static int 433 deflateq_done(struct virtqueue *vq) 434 { 435 struct virtio_softc *vsc = vq->vq_owner; 436 struct viomb_softc *sc = device_private(vsc->sc_child); 437 438 mutex_enter(&sc->sc_waitlock); 439 sc->sc_deflate_done = 1; 440 cv_signal(&sc->sc_wait); 441 mutex_exit(&sc->sc_waitlock); 442 443 return 1; 444 } 445 446 static int 447 deflate_done(struct viomb_softc *sc) 448 { 449 struct virtio_softc *vsc = sc->sc_virtio; 450 struct virtqueue *vq = &sc->sc_vq[1]; 451 struct balloon_req *b; 452 int r, slot; 453 uint64_t nvpages; 454 455 r = virtio_dequeue(vsc, vq, &slot, NULL); 456 if (r != 0) { 457 printf("%s: deflate dequeue failed, errno %d\n", 458 device_xname(sc->sc_dev), r); 459 return 1; 460 } 461 virtio_dequeue_commit(vsc, vq, slot); 462 463 b = &sc->sc_req; 464 nvpages = b->bl_nentries; 465 bus_dmamap_sync(vsc->sc_dmat, b->bl_dmamap, 466 offsetof(struct balloon_req, bl_pages), 467 sizeof(uint32_t)*nvpages, 468 BUS_DMASYNC_POSTWRITE); 469 470 if (vsc->sc_features & VIRTIO_BALLOON_F_MUST_TELL_HOST) 471 uvm_pglistfree(&b->bl_pglist); 472 473 sc->sc_inflight += nvpages; 474 virtio_write_device_config_4(vsc, 475 VIRTIO_BALLOON_CONFIG_ACTUAL, 476 sc->sc_actual - nvpages); 477 viomb_read_config(sc); 478 479 return 1; 480 } 481 482 /* 483 * Kthread: sleeps, eventually inflate and deflate. 484 */ 485 static void 486 viomb_thread(void *arg) 487 { 488 struct viomb_softc *sc = arg; 489 int sleeptime, r; 490 491 for ( ; ; ) { 492 sleeptime = 30000; 493 if (sc->sc_npages > sc->sc_actual + sc->sc_inflight) { 494 if (sc->sc_inflight == 0) { 495 r = inflate(sc); 496 if (r != 0) 497 sleeptime = 10000; 498 else 499 sleeptime = 1000; 500 } else 501 sleeptime = 100; 502 } else if (sc->sc_npages < sc->sc_actual + sc->sc_inflight) { 503 if (sc->sc_inflight == 0) 504 r = deflate(sc); 505 sleeptime = 100; 506 } 507 508 again: 509 mutex_enter(&sc->sc_waitlock); 510 if (sc->sc_inflate_done) { 511 sc->sc_inflate_done = 0; 512 mutex_exit(&sc->sc_waitlock); 513 inflate_done(sc); 514 goto again; 515 } 516 if (sc->sc_deflate_done) { 517 sc->sc_deflate_done = 0; 518 mutex_exit(&sc->sc_waitlock); 519 deflate_done(sc); 520 goto again; 521 } 522 cv_timedwait(&sc->sc_wait, &sc->sc_waitlock, 523 mstohz(sleeptime)); 524 mutex_exit(&sc->sc_waitlock); 525 } 526 } 527