1 /* $NetBSD: viomb.c,v 1.9 2018/06/10 14:59:23 jakllsch 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.9 2018/06/10 14:59:23 jakllsch 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 #include <sys/module.h> 42 43 #include <dev/pci/virtioreg.h> 44 #include <dev/pci/virtiovar.h> 45 46 #include "ioconf.h" 47 48 /* Configuration registers */ 49 #define VIRTIO_BALLOON_CONFIG_NUM_PAGES 0 /* 32bit */ 50 #define VIRTIO_BALLOON_CONFIG_ACTUAL 4 /* 32bit */ 51 52 /* Feature bits */ 53 #define VIRTIO_BALLOON_F_MUST_TELL_HOST (1<<0) 54 #define VIRTIO_BALLOON_F_STATS_VQ (1<<1) 55 56 #define VIRTIO_BALLOON_FLAG_BITS \ 57 VIRTIO_COMMON_FLAG_BITS \ 58 "\x02""STATS_VQ" \ 59 "\x01""MUST_TELL_HOST" 60 61 #define PGS_PER_REQ (256) /* 1MB, 4KB/page */ 62 63 CTASSERT((PAGE_SIZE) == (VIRTIO_PAGE_SIZE)); /* XXX */ 64 65 struct balloon_req { 66 bus_dmamap_t bl_dmamap; 67 struct pglist bl_pglist; 68 int bl_nentries; 69 uint32_t bl_pages[PGS_PER_REQ]; 70 }; 71 72 struct viomb_softc { 73 device_t sc_dev; 74 75 struct virtio_softc *sc_virtio; 76 struct virtqueue sc_vq[2]; 77 78 unsigned int sc_npages; 79 unsigned int sc_actual; 80 int sc_inflight; 81 struct balloon_req sc_req; 82 struct pglist sc_balloon_pages; 83 84 int sc_inflate_done; 85 int sc_deflate_done; 86 87 kcondvar_t sc_wait; 88 kmutex_t sc_waitlock; 89 }; 90 91 static int balloon_initialized = 0; /* multiple balloon is not allowed */ 92 93 static int viomb_match(device_t, cfdata_t, void *); 94 static void viomb_attach(device_t, device_t, void *); 95 static void viomb_read_config(struct viomb_softc *); 96 static int viomb_config_change(struct virtio_softc *); 97 static int inflate(struct viomb_softc *); 98 static int inflateq_done(struct virtqueue *); 99 static int inflate_done(struct viomb_softc *); 100 static int deflate(struct viomb_softc *); 101 static int deflateq_done(struct virtqueue *); 102 static int deflate_done(struct viomb_softc *); 103 static void viomb_thread(void *); 104 105 CFATTACH_DECL_NEW(viomb, sizeof(struct viomb_softc), 106 viomb_match, viomb_attach, NULL, NULL); 107 108 static int 109 viomb_match(device_t parent, cfdata_t match, void *aux) 110 { 111 struct virtio_attach_args *va = aux; 112 113 if (va->sc_childdevid == PCI_PRODUCT_VIRTIO_BALLOON) 114 return 1; 115 116 return 0; 117 } 118 119 static void 120 viomb_attach(device_t parent, device_t self, void *aux) 121 { 122 struct viomb_softc *sc = device_private(self); 123 struct virtio_softc *vsc = device_private(parent); 124 const struct sysctlnode *node; 125 126 if (virtio_child(vsc) != NULL) { 127 aprint_normal(": child already attached for %s; " 128 "something wrong...\n", device_xname(parent)); 129 return; 130 } 131 132 if (balloon_initialized++) { 133 aprint_normal(": balloon already exists; something wrong...\n"); 134 goto err_none; 135 } 136 137 sc->sc_dev = self; 138 sc->sc_virtio = vsc; 139 140 if ((virtio_alloc_vq(vsc, &sc->sc_vq[0], 0, 141 sizeof(uint32_t)*PGS_PER_REQ, 1, 142 "inflate") != 0) || 143 (virtio_alloc_vq(vsc, &sc->sc_vq[1], 1, 144 sizeof(uint32_t)*PGS_PER_REQ, 1, 145 "deflate") != 0)) { 146 goto err_none; 147 } 148 sc->sc_vq[0].vq_done = inflateq_done; 149 sc->sc_vq[1].vq_done = deflateq_done; 150 151 viomb_read_config(sc); 152 sc->sc_inflight = 0; 153 TAILQ_INIT(&sc->sc_balloon_pages); 154 155 if (bus_dmamap_create(virtio_dmat(vsc), sizeof(uint32_t)*PGS_PER_REQ, 156 1, sizeof(uint32_t)*PGS_PER_REQ, 0, 157 BUS_DMA_NOWAIT, &sc->sc_req.bl_dmamap)) { 158 aprint_error_dev(sc->sc_dev, "dmamap creation failed.\n"); 159 goto err_vq; 160 } 161 if (bus_dmamap_load(virtio_dmat(vsc), sc->sc_req.bl_dmamap, 162 &sc->sc_req.bl_pages[0], 163 sizeof(uint32_t) * PGS_PER_REQ, 164 NULL, BUS_DMA_NOWAIT)) { 165 aprint_error_dev(sc->sc_dev, "dmamap load failed.\n"); 166 goto err_dmamap; 167 } 168 169 sc->sc_inflate_done = sc->sc_deflate_done = 0; 170 mutex_init(&sc->sc_waitlock, MUTEX_DEFAULT, IPL_VM); /* spin */ 171 cv_init(&sc->sc_wait, "balloon"); 172 173 virtio_child_attach_start(vsc, self, IPL_VM, sc->sc_vq, 174 viomb_config_change, virtio_vq_intr, 0, 175 0, VIRTIO_BALLOON_FLAG_BITS); 176 177 if (virtio_child_attach_finish(vsc) != 0) 178 goto err_mutex; 179 180 if (kthread_create(PRI_IDLE, KTHREAD_MPSAFE, NULL, 181 viomb_thread, sc, NULL, "viomb")) { 182 aprint_error_dev(sc->sc_dev, "cannot create kthread.\n"); 183 goto err_mutex; 184 } 185 186 sysctl_createv(NULL, 0, NULL, &node, 0, CTLTYPE_NODE, 187 "viomb", SYSCTL_DESCR("VirtIO Balloon status"), 188 NULL, 0, NULL, 0, 189 CTL_HW, CTL_CREATE, CTL_EOL); 190 sysctl_createv(NULL, 0, NULL, NULL, 0, CTLTYPE_INT, 191 "npages", SYSCTL_DESCR("VirtIO Balloon npages value"), 192 NULL, 0, &sc->sc_npages, 0, 193 CTL_HW, node->sysctl_num, CTL_CREATE, CTL_EOL); 194 sysctl_createv(NULL, 0, NULL, NULL, 0, CTLTYPE_INT, 195 "actual", SYSCTL_DESCR("VirtIO Balloon actual value"), 196 NULL, 0, &sc->sc_actual, 0, 197 CTL_HW, node->sysctl_num, CTL_CREATE, CTL_EOL); 198 return; 199 200 err_mutex: 201 cv_destroy(&sc->sc_wait); 202 mutex_destroy(&sc->sc_waitlock); 203 err_dmamap: 204 bus_dmamap_destroy(virtio_dmat(vsc), sc->sc_req.bl_dmamap); 205 err_vq: 206 virtio_free_vq(vsc, &sc->sc_vq[1]); 207 virtio_free_vq(vsc, &sc->sc_vq[0]); 208 err_none: 209 virtio_child_attach_failed(vsc); 210 return; 211 } 212 213 static void 214 viomb_read_config(struct viomb_softc *sc) 215 { 216 unsigned int reg; 217 218 /* these values are explicitly specified as little-endian */ 219 reg = virtio_read_device_config_4(sc->sc_virtio, 220 VIRTIO_BALLOON_CONFIG_NUM_PAGES); 221 sc->sc_npages = le32toh(reg); 222 223 reg = virtio_read_device_config_4(sc->sc_virtio, 224 VIRTIO_BALLOON_CONFIG_ACTUAL); 225 sc->sc_actual = le32toh(reg); 226 } 227 228 /* 229 * Config change callback: wakeup the kthread. 230 */ 231 static int 232 viomb_config_change(struct virtio_softc *vsc) 233 { 234 struct viomb_softc *sc = device_private(virtio_child(vsc)); 235 unsigned int old; 236 237 old = sc->sc_npages; 238 viomb_read_config(sc); 239 mutex_enter(&sc->sc_waitlock); 240 cv_signal(&sc->sc_wait); 241 mutex_exit(&sc->sc_waitlock); 242 if (sc->sc_npages > old) 243 printf("%s: inflating balloon from %u to %u.\n", 244 device_xname(sc->sc_dev), old, sc->sc_npages); 245 else if (sc->sc_npages < old) 246 printf("%s: deflating balloon from %u to %u.\n", 247 device_xname(sc->sc_dev), old, sc->sc_npages); 248 249 return 1; 250 } 251 252 /* 253 * Inflate: consume some amount of physical memory. 254 */ 255 static int 256 inflate(struct viomb_softc *sc) 257 { 258 struct virtio_softc *vsc = sc->sc_virtio; 259 int i, slot; 260 uint64_t nvpages, nhpages; 261 struct balloon_req *b; 262 struct vm_page *p; 263 struct virtqueue *vq = &sc->sc_vq[0]; 264 265 if (sc->sc_inflight) 266 return 0; 267 nvpages = sc->sc_npages - sc->sc_actual; 268 if (nvpages > PGS_PER_REQ) 269 nvpages = PGS_PER_REQ; 270 nhpages = nvpages * VIRTIO_PAGE_SIZE / PAGE_SIZE; 271 272 b = &sc->sc_req; 273 if (uvm_pglistalloc(nhpages*PAGE_SIZE, 0, UINT32_MAX*PAGE_SIZE, 274 0, 0, &b->bl_pglist, nhpages, 1)) { 275 printf("%s: %" PRIu64 " pages of physical memory " 276 "could not be allocated, retrying...\n", 277 device_xname(sc->sc_dev), nhpages); 278 return 1; /* sleep longer */ 279 } 280 281 b->bl_nentries = nvpages; 282 i = 0; 283 TAILQ_FOREACH(p, &b->bl_pglist, pageq.queue) { 284 b->bl_pages[i++] = p->phys_addr / VIRTIO_PAGE_SIZE; 285 } 286 KASSERT(i == nvpages); 287 288 if (virtio_enqueue_prep(vsc, vq, &slot) != 0) { 289 printf("%s: inflate enqueue failed.\n", 290 device_xname(sc->sc_dev)); 291 uvm_pglistfree(&b->bl_pglist); 292 return 0; 293 } 294 if (virtio_enqueue_reserve(vsc, vq, slot, 1)) { 295 printf("%s: inflate enqueue failed.\n", 296 device_xname(sc->sc_dev)); 297 uvm_pglistfree(&b->bl_pglist); 298 return 0; 299 } 300 bus_dmamap_sync(virtio_dmat(vsc), b->bl_dmamap, 0, 301 sizeof(uint32_t)*nvpages, BUS_DMASYNC_PREWRITE); 302 virtio_enqueue(vsc, vq, slot, b->bl_dmamap, true); 303 virtio_enqueue_commit(vsc, vq, slot, true); 304 sc->sc_inflight += nvpages; 305 306 return 0; 307 } 308 309 static int 310 inflateq_done(struct virtqueue *vq) 311 { 312 struct virtio_softc *vsc = vq->vq_owner; 313 struct viomb_softc *sc = device_private(virtio_child(vsc)); 314 315 mutex_enter(&sc->sc_waitlock); 316 sc->sc_inflate_done = 1; 317 cv_signal(&sc->sc_wait); 318 mutex_exit(&sc->sc_waitlock); 319 320 return 1; 321 } 322 323 static int 324 inflate_done(struct viomb_softc *sc) 325 { 326 struct virtio_softc *vsc = sc->sc_virtio; 327 struct virtqueue *vq = &sc->sc_vq[0]; 328 struct balloon_req *b; 329 int r, slot; 330 uint64_t nvpages; 331 struct vm_page *p; 332 333 r = virtio_dequeue(vsc, vq, &slot, NULL); 334 if (r != 0) { 335 printf("%s: inflate dequeue failed, errno %d.\n", 336 device_xname(sc->sc_dev), r); 337 return 1; 338 } 339 virtio_dequeue_commit(vsc, vq, slot); 340 341 b = &sc->sc_req; 342 nvpages = b->bl_nentries; 343 bus_dmamap_sync(virtio_dmat(vsc), b->bl_dmamap, 344 offsetof(struct balloon_req, bl_pages), 345 sizeof(uint32_t)*nvpages, 346 BUS_DMASYNC_POSTWRITE); 347 while (!TAILQ_EMPTY(&b->bl_pglist)) { 348 p = TAILQ_FIRST(&b->bl_pglist); 349 TAILQ_REMOVE(&b->bl_pglist, p, pageq.queue); 350 TAILQ_INSERT_TAIL(&sc->sc_balloon_pages, p, pageq.queue); 351 } 352 353 sc->sc_inflight -= nvpages; 354 virtio_write_device_config_4(vsc, 355 VIRTIO_BALLOON_CONFIG_ACTUAL, 356 sc->sc_actual + nvpages); 357 viomb_read_config(sc); 358 359 return 1; 360 } 361 362 /* 363 * Deflate: free previously allocated memory. 364 */ 365 static int 366 deflate(struct viomb_softc *sc) 367 { 368 struct virtio_softc *vsc = sc->sc_virtio; 369 int i, slot; 370 uint64_t nvpages, nhpages; 371 struct balloon_req *b; 372 struct vm_page *p; 373 struct virtqueue *vq = &sc->sc_vq[1]; 374 375 nvpages = (sc->sc_actual + sc->sc_inflight) - sc->sc_npages; 376 if (nvpages > PGS_PER_REQ) 377 nvpages = PGS_PER_REQ; 378 nhpages = nvpages * VIRTIO_PAGE_SIZE / PAGE_SIZE; 379 380 b = &sc->sc_req; 381 382 b->bl_nentries = nvpages; 383 TAILQ_INIT(&b->bl_pglist); 384 for (i = 0; i < nhpages; i++) { 385 p = TAILQ_FIRST(&sc->sc_balloon_pages); 386 if (p == NULL) 387 break; 388 TAILQ_REMOVE(&sc->sc_balloon_pages, p, pageq.queue); 389 TAILQ_INSERT_TAIL(&b->bl_pglist, p, pageq.queue); 390 b->bl_pages[i] = p->phys_addr / VIRTIO_PAGE_SIZE; 391 } 392 393 if (virtio_enqueue_prep(vsc, vq, &slot) != 0) { 394 printf("%s: deflate enqueue failed.\n", 395 device_xname(sc->sc_dev)); 396 TAILQ_FOREACH_REVERSE(p, &b->bl_pglist, pglist, pageq.queue) { 397 TAILQ_REMOVE(&b->bl_pglist, p, pageq.queue); 398 TAILQ_INSERT_HEAD(&sc->sc_balloon_pages, p, 399 pageq.queue); 400 } 401 return 0; 402 } 403 if (virtio_enqueue_reserve(vsc, vq, slot, 1) != 0) { 404 printf("%s: deflate enqueue failed.\n", 405 device_xname(sc->sc_dev)); 406 TAILQ_FOREACH_REVERSE(p, &b->bl_pglist, pglist, pageq.queue) { 407 TAILQ_REMOVE(&b->bl_pglist, p, pageq.queue); 408 TAILQ_INSERT_HEAD(&sc->sc_balloon_pages, p, 409 pageq.queue); 410 } 411 return 0; 412 } 413 bus_dmamap_sync(virtio_dmat(vsc), b->bl_dmamap, 0, 414 sizeof(uint32_t)*nvpages, BUS_DMASYNC_PREWRITE); 415 virtio_enqueue(vsc, vq, slot, b->bl_dmamap, true); 416 virtio_enqueue_commit(vsc, vq, slot, true); 417 sc->sc_inflight -= nvpages; 418 419 if (!(virtio_features(vsc) & VIRTIO_BALLOON_F_MUST_TELL_HOST)) 420 uvm_pglistfree(&b->bl_pglist); 421 422 return 0; 423 } 424 425 static int 426 deflateq_done(struct virtqueue *vq) 427 { 428 struct virtio_softc *vsc = vq->vq_owner; 429 struct viomb_softc *sc = device_private(virtio_child(vsc)); 430 431 mutex_enter(&sc->sc_waitlock); 432 sc->sc_deflate_done = 1; 433 cv_signal(&sc->sc_wait); 434 mutex_exit(&sc->sc_waitlock); 435 436 return 1; 437 } 438 439 static int 440 deflate_done(struct viomb_softc *sc) 441 { 442 struct virtio_softc *vsc = sc->sc_virtio; 443 struct virtqueue *vq = &sc->sc_vq[1]; 444 struct balloon_req *b; 445 int r, slot; 446 uint64_t nvpages; 447 448 r = virtio_dequeue(vsc, vq, &slot, NULL); 449 if (r != 0) { 450 printf("%s: deflate dequeue failed, errno %d\n", 451 device_xname(sc->sc_dev), r); 452 return 1; 453 } 454 virtio_dequeue_commit(vsc, vq, slot); 455 456 b = &sc->sc_req; 457 nvpages = b->bl_nentries; 458 bus_dmamap_sync(virtio_dmat(vsc), b->bl_dmamap, 459 offsetof(struct balloon_req, bl_pages), 460 sizeof(uint32_t)*nvpages, 461 BUS_DMASYNC_POSTWRITE); 462 463 if (virtio_features(vsc) & VIRTIO_BALLOON_F_MUST_TELL_HOST) 464 uvm_pglistfree(&b->bl_pglist); 465 466 sc->sc_inflight += nvpages; 467 virtio_write_device_config_4(vsc, 468 VIRTIO_BALLOON_CONFIG_ACTUAL, 469 sc->sc_actual - nvpages); 470 viomb_read_config(sc); 471 472 return 1; 473 } 474 475 /* 476 * Kthread: sleeps, eventually inflate and deflate. 477 */ 478 static void 479 viomb_thread(void *arg) 480 { 481 struct viomb_softc *sc = arg; 482 int sleeptime, r; 483 484 for ( ; ; ) { 485 sleeptime = 30000; 486 if (sc->sc_npages > sc->sc_actual + sc->sc_inflight) { 487 if (sc->sc_inflight == 0) { 488 r = inflate(sc); 489 if (r != 0) 490 sleeptime = 10000; 491 else 492 sleeptime = 1000; 493 } else 494 sleeptime = 100; 495 } else if (sc->sc_npages < sc->sc_actual + sc->sc_inflight) { 496 if (sc->sc_inflight == 0) 497 r = deflate(sc); 498 sleeptime = 100; 499 } 500 501 again: 502 mutex_enter(&sc->sc_waitlock); 503 if (sc->sc_inflate_done) { 504 sc->sc_inflate_done = 0; 505 mutex_exit(&sc->sc_waitlock); 506 inflate_done(sc); 507 goto again; 508 } 509 if (sc->sc_deflate_done) { 510 sc->sc_deflate_done = 0; 511 mutex_exit(&sc->sc_waitlock); 512 deflate_done(sc); 513 goto again; 514 } 515 cv_timedwait(&sc->sc_wait, &sc->sc_waitlock, 516 mstohz(sleeptime)); 517 mutex_exit(&sc->sc_waitlock); 518 } 519 } 520 521 MODULE(MODULE_CLASS_DRIVER, viomb, "virtio"); 522 523 #ifdef _MODULE 524 #include "ioconf.c" 525 #endif 526 527 static int 528 viomb_modcmd(modcmd_t cmd, void *opaque) 529 { 530 int error = 0; 531 532 #ifdef _MODULE 533 switch (cmd) { 534 case MODULE_CMD_INIT: 535 error = config_init_component(cfdriver_ioconf_viomb, 536 cfattach_ioconf_viomb, cfdata_ioconf_viomb); 537 break; 538 case MODULE_CMD_FINI: 539 error = config_fini_component(cfdriver_ioconf_viomb, 540 cfattach_ioconf_viomb, cfdata_ioconf_viomb); 541 break; 542 default: 543 error = ENOTTY; 544 break; 545 } 546 #endif 547 548 return error; 549 } 550