1 /* $OpenBSD: virtio_mmio.c,v 1.12 2024/01/15 02:35:23 dv Exp $ */ 2 /* $NetBSD: virtio.c,v 1.3 2011/11/02 23:05:52 njoly Exp $ */ 3 4 /* 5 * Copyright (c) 2014 Patrick Wildt <patrick@blueri.se> 6 * Copyright (c) 2012 Stefan Fritsch. 7 * Copyright (c) 2010 Minoura Makoto. 8 * All rights reserved. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 20 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 21 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 22 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 23 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 24 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 28 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 */ 30 31 #include <sys/param.h> 32 #include <sys/systm.h> 33 #include <sys/kernel.h> 34 #include <sys/device.h> 35 #include <sys/mutex.h> 36 37 #include <dev/pv/virtioreg.h> 38 #include <dev/pv/virtiovar.h> 39 40 #include <machine/fdt.h> 41 42 #include <dev/ofw/fdt.h> 43 #include <dev/ofw/openfirm.h> 44 45 #define VIRTIO_MMIO_MAGIC ('v' | 'i' << 8 | 'r' << 16 | 't' << 24) 46 47 #define VIRTIO_MMIO_MAGIC_VALUE 0x000 48 #define VIRTIO_MMIO_VERSION 0x004 49 #define VIRTIO_MMIO_DEVICE_ID 0x008 50 #define VIRTIO_MMIO_VENDOR_ID 0x00c 51 #define VIRTIO_MMIO_HOST_FEATURES 0x010 52 #define VIRTIO_MMIO_HOST_FEATURES_SEL 0x014 53 #define VIRTIO_MMIO_GUEST_FEATURES 0x020 54 #define VIRTIO_MMIO_GUEST_FEATURES_SEL 0x024 55 #define VIRTIO_MMIO_GUEST_PAGE_SIZE 0x028 56 #define VIRTIO_MMIO_QUEUE_SEL 0x030 57 #define VIRTIO_MMIO_QUEUE_NUM_MAX 0x034 58 #define VIRTIO_MMIO_QUEUE_NUM 0x038 59 #define VIRTIO_MMIO_QUEUE_ALIGN 0x03c 60 #define VIRTIO_MMIO_QUEUE_PFN 0x040 61 #define VIRTIO_MMIO_QUEUE_READY 0x044 62 #define VIRTIO_MMIO_QUEUE_NOTIFY 0x050 63 #define VIRTIO_MMIO_INTERRUPT_STATUS 0x060 64 #define VIRTIO_MMIO_INTERRUPT_ACK 0x064 65 #define VIRTIO_MMIO_STATUS 0x070 66 #define VIRTIO_MMIO_QUEUE_DESC_LOW 0x080 67 #define VIRTIO_MMIO_QUEUE_DESC_HIGH 0x084 68 #define VIRTIO_MMIO_QUEUE_AVAIL_LOW 0x090 69 #define VIRTIO_MMIO_QUEUE_AVAIL_HIGH 0x094 70 #define VIRTIO_MMIO_QUEUE_USED_LOW 0x0a0 71 #define VIRTIO_MMIO_QUEUE_USED_HIGH 0x0a4 72 #define VIRTIO_MMIO_CONFIG 0x100 73 74 #define VIRTIO_MMIO_INT_VRING (1 << 0) 75 #define VIRTIO_MMIO_INT_CONFIG (1 << 1) 76 77 #define DEVNAME(sc) (sc)->sc_dev.dv_xname 78 79 /* 80 * XXX: Before being used on big endian arches, the access to config registers 81 * XXX: needs to be reviewed/fixed. The non-device specific registers are 82 * XXX: PCI-endian while the device specific registers are native endian. 83 */ 84 85 int virtio_mmio_match(struct device *, void *, void *); 86 void virtio_mmio_attach(struct device *, struct device *, void *); 87 int virtio_mmio_detach(struct device *, int); 88 89 void virtio_mmio_kick(struct virtio_softc *, uint16_t); 90 uint8_t virtio_mmio_read_device_config_1(struct virtio_softc *, int); 91 uint16_t virtio_mmio_read_device_config_2(struct virtio_softc *, int); 92 uint32_t virtio_mmio_read_device_config_4(struct virtio_softc *, int); 93 uint64_t virtio_mmio_read_device_config_8(struct virtio_softc *, int); 94 void virtio_mmio_write_device_config_1(struct virtio_softc *, int, uint8_t); 95 void virtio_mmio_write_device_config_2(struct virtio_softc *, int, uint16_t); 96 void virtio_mmio_write_device_config_4(struct virtio_softc *, int, uint32_t); 97 void virtio_mmio_write_device_config_8(struct virtio_softc *, int, uint64_t); 98 uint16_t virtio_mmio_read_queue_size(struct virtio_softc *, uint16_t); 99 void virtio_mmio_setup_queue(struct virtio_softc *, struct virtqueue *, uint64_t); 100 void virtio_mmio_set_status(struct virtio_softc *, int); 101 int virtio_mmio_negotiate_features(struct virtio_softc *, 102 const struct virtio_feature_name *); 103 int virtio_mmio_intr(void *); 104 105 struct virtio_mmio_softc { 106 struct virtio_softc sc_sc; 107 108 bus_space_tag_t sc_iot; 109 bus_space_handle_t sc_ioh; 110 bus_size_t sc_iosize; 111 bus_dma_tag_t sc_dmat; 112 113 void *sc_ih; 114 115 int sc_config_offset; 116 uint32_t sc_version; 117 }; 118 119 const struct cfattach virtio_mmio_ca = { 120 sizeof(struct virtio_mmio_softc), 121 virtio_mmio_match, 122 virtio_mmio_attach, 123 virtio_mmio_detach, 124 NULL 125 }; 126 127 const struct cfattach virtio_mmio_fdt_ca = { 128 sizeof(struct virtio_mmio_softc), 129 NULL, 130 virtio_mmio_attach, 131 virtio_mmio_detach, 132 NULL 133 }; 134 135 struct virtio_ops virtio_mmio_ops = { 136 virtio_mmio_kick, 137 virtio_mmio_read_device_config_1, 138 virtio_mmio_read_device_config_2, 139 virtio_mmio_read_device_config_4, 140 virtio_mmio_read_device_config_8, 141 virtio_mmio_write_device_config_1, 142 virtio_mmio_write_device_config_2, 143 virtio_mmio_write_device_config_4, 144 virtio_mmio_write_device_config_8, 145 virtio_mmio_read_queue_size, 146 virtio_mmio_setup_queue, 147 virtio_mmio_set_status, 148 virtio_mmio_negotiate_features, 149 virtio_mmio_intr, 150 }; 151 152 uint16_t 153 virtio_mmio_read_queue_size(struct virtio_softc *vsc, uint16_t idx) 154 { 155 struct virtio_mmio_softc *sc = (struct virtio_mmio_softc *)vsc; 156 bus_space_write_4(sc->sc_iot, sc->sc_ioh, VIRTIO_MMIO_QUEUE_SEL, idx); 157 return bus_space_read_4(sc->sc_iot, sc->sc_ioh, 158 VIRTIO_MMIO_QUEUE_NUM_MAX); 159 } 160 161 void 162 virtio_mmio_setup_queue(struct virtio_softc *vsc, struct virtqueue *vq, 163 uint64_t addr) 164 { 165 struct virtio_mmio_softc *sc = (struct virtio_mmio_softc *)vsc; 166 bus_space_write_4(sc->sc_iot, sc->sc_ioh, VIRTIO_MMIO_QUEUE_SEL, 167 vq->vq_index); 168 bus_space_write_4(sc->sc_iot, sc->sc_ioh, VIRTIO_MMIO_QUEUE_NUM, 169 bus_space_read_4(sc->sc_iot, sc->sc_ioh, VIRTIO_MMIO_QUEUE_NUM_MAX)); 170 if (sc->sc_version == 1) { 171 bus_space_write_4(sc->sc_iot, sc->sc_ioh, 172 VIRTIO_MMIO_QUEUE_ALIGN, PAGE_SIZE); 173 bus_space_write_4(sc->sc_iot, sc->sc_ioh, 174 VIRTIO_MMIO_QUEUE_PFN, addr / VIRTIO_PAGE_SIZE); 175 } else { 176 bus_space_write_4(sc->sc_iot, sc->sc_ioh, 177 VIRTIO_MMIO_QUEUE_DESC_LOW, addr); 178 bus_space_write_4(sc->sc_iot, sc->sc_ioh, 179 VIRTIO_MMIO_QUEUE_DESC_HIGH, addr >> 32); 180 bus_space_write_4(sc->sc_iot, sc->sc_ioh, 181 VIRTIO_MMIO_QUEUE_AVAIL_LOW, 182 addr + vq->vq_availoffset); 183 bus_space_write_4(sc->sc_iot, sc->sc_ioh, 184 VIRTIO_MMIO_QUEUE_AVAIL_HIGH, 185 (addr + vq->vq_availoffset) >> 32); 186 bus_space_write_4(sc->sc_iot, sc->sc_ioh, 187 VIRTIO_MMIO_QUEUE_USED_LOW, 188 addr + vq->vq_usedoffset); 189 bus_space_write_4(sc->sc_iot, sc->sc_ioh, 190 VIRTIO_MMIO_QUEUE_USED_HIGH, 191 (addr + vq->vq_usedoffset) >> 32); 192 bus_space_write_4(sc->sc_iot, sc->sc_ioh, 193 VIRTIO_MMIO_QUEUE_READY, 1); 194 } 195 } 196 197 void 198 virtio_mmio_set_status(struct virtio_softc *vsc, int status) 199 { 200 struct virtio_mmio_softc *sc = (struct virtio_mmio_softc *)vsc; 201 int old = 0; 202 203 if (status == 0) { 204 bus_space_write_4(sc->sc_iot, sc->sc_ioh, VIRTIO_MMIO_STATUS, 205 0); 206 while (bus_space_read_4(sc->sc_iot, sc->sc_ioh, 207 VIRTIO_MMIO_STATUS) != 0) { 208 CPU_BUSY_CYCLE(); 209 } 210 } else { 211 old = bus_space_read_4(sc->sc_iot, sc->sc_ioh, 212 VIRTIO_MMIO_STATUS); 213 bus_space_write_4(sc->sc_iot, sc->sc_ioh, VIRTIO_MMIO_STATUS, 214 status|old); 215 } 216 } 217 218 int 219 virtio_mmio_match(struct device *parent, void *cfdata, void *aux) 220 { 221 struct fdt_attach_args *faa = aux; 222 223 return OF_is_compatible(faa->fa_node, "virtio,mmio"); 224 } 225 226 void 227 virtio_mmio_attach(struct device *parent, struct device *self, void *aux) 228 { 229 struct fdt_attach_args *faa = aux; 230 struct virtio_mmio_softc *sc = (struct virtio_mmio_softc *)self; 231 struct virtio_softc *vsc = &sc->sc_sc; 232 uint32_t id, magic; 233 234 if (faa->fa_nreg < 1) { 235 printf(": no register data\n"); 236 return; 237 } 238 239 sc->sc_iosize = faa->fa_reg[0].size; 240 sc->sc_iot = faa->fa_iot; 241 sc->sc_dmat = faa->fa_dmat; 242 if (bus_space_map(sc->sc_iot, faa->fa_reg[0].addr, faa->fa_reg[0].size, 243 0, &sc->sc_ioh)) 244 panic("%s: bus_space_map failed!", __func__); 245 246 magic = bus_space_read_4(sc->sc_iot, sc->sc_ioh, 247 VIRTIO_MMIO_MAGIC_VALUE); 248 if (magic != VIRTIO_MMIO_MAGIC) { 249 printf(": wrong magic value 0x%08x; giving up\n", magic); 250 return; 251 } 252 253 sc->sc_version = bus_space_read_4(sc->sc_iot, sc->sc_ioh, 254 VIRTIO_MMIO_VERSION); 255 if (sc->sc_version < 1 || sc->sc_version > 2) { 256 printf(": unknown version 0x%02x; giving up\n", sc->sc_version); 257 return; 258 } 259 260 id = bus_space_read_4(sc->sc_iot, sc->sc_ioh, VIRTIO_MMIO_DEVICE_ID); 261 printf(": Virtio %s Device", virtio_device_string(id)); 262 263 if (sc->sc_version == 1) 264 bus_space_write_4(sc->sc_iot, sc->sc_ioh, 265 VIRTIO_MMIO_GUEST_PAGE_SIZE, PAGE_SIZE); 266 267 printf("\n"); 268 269 /* No device connected. */ 270 if (id == 0) 271 return; 272 273 vsc->sc_ops = &virtio_mmio_ops; 274 vsc->sc_dmat = sc->sc_dmat; 275 sc->sc_config_offset = VIRTIO_MMIO_CONFIG; 276 277 virtio_device_reset(vsc); 278 virtio_mmio_set_status(vsc, VIRTIO_CONFIG_DEVICE_STATUS_ACK); 279 virtio_mmio_set_status(vsc, VIRTIO_CONFIG_DEVICE_STATUS_DRIVER); 280 281 /* XXX: use softc as aux... */ 282 vsc->sc_childdevid = id; 283 vsc->sc_child = NULL; 284 config_found(self, sc, NULL); 285 if (vsc->sc_child == NULL) { 286 printf("%s: no matching child driver; not configured\n", 287 vsc->sc_dev.dv_xname); 288 goto fail_1; 289 } 290 if (vsc->sc_child == VIRTIO_CHILD_ERROR) { 291 printf("%s: virtio configuration failed\n", 292 vsc->sc_dev.dv_xname); 293 goto fail_1; 294 } 295 296 sc->sc_ih = fdt_intr_establish(faa->fa_node, vsc->sc_ipl, 297 virtio_mmio_intr, sc, vsc->sc_dev.dv_xname); 298 if (sc->sc_ih == NULL) { 299 printf("%s: couldn't establish interrupt\n", 300 vsc->sc_dev.dv_xname); 301 goto fail_2; 302 } 303 304 return; 305 306 fail_2: 307 config_detach(vsc->sc_child, 0); 308 fail_1: 309 /* no mmio_mapreg_unmap() or mmio_intr_unmap() */ 310 virtio_set_status(vsc, VIRTIO_CONFIG_DEVICE_STATUS_FAILED); 311 } 312 313 int 314 virtio_mmio_detach(struct device *self, int flags) 315 { 316 struct virtio_mmio_softc *sc = (struct virtio_mmio_softc *)self; 317 struct virtio_softc *vsc = &sc->sc_sc; 318 int r; 319 320 if (vsc->sc_child != 0 && vsc->sc_child != VIRTIO_CHILD_ERROR) { 321 r = config_detach(vsc->sc_child, flags); 322 if (r) 323 return r; 324 } 325 KASSERT(vsc->sc_child == 0 || vsc->sc_child == VIRTIO_CHILD_ERROR); 326 KASSERT(vsc->sc_vqs == 0); 327 fdt_intr_disestablish(sc->sc_ih); 328 sc->sc_ih = 0; 329 if (sc->sc_iosize) 330 bus_space_unmap(sc->sc_iot, sc->sc_ioh, sc->sc_iosize); 331 sc->sc_iosize = 0; 332 333 return 0; 334 } 335 336 /* 337 * Feature negotiation. 338 * Prints available / negotiated features if guest_feature_names != NULL and 339 * VIRTIO_DEBUG is 1 340 */ 341 int 342 virtio_mmio_negotiate_features(struct virtio_softc *vsc, 343 const struct virtio_feature_name *guest_feature_names) 344 { 345 struct virtio_mmio_softc *sc = (struct virtio_mmio_softc *)vsc; 346 uint64_t host, neg; 347 348 vsc->sc_active_features = 0; 349 350 /* 351 * We enable indirect descriptors by default. They can be switched 352 * off by setting bit 1 in the driver flags, see config(8). 353 */ 354 if (!(vsc->sc_dev.dv_cfdata->cf_flags & VIRTIO_CF_NO_INDIRECT) && 355 !(vsc->sc_child->dv_cfdata->cf_flags & VIRTIO_CF_NO_INDIRECT)) { 356 vsc->sc_driver_features |= VIRTIO_F_RING_INDIRECT_DESC; 357 } else if (guest_feature_names != NULL) { 358 printf("RingIndirectDesc disabled by UKC\n"); 359 } 360 /* 361 * The driver must add VIRTIO_F_RING_EVENT_IDX if it supports it. 362 * If it did, check if it is disabled by bit 2 in the driver flags. 363 */ 364 if ((vsc->sc_driver_features & VIRTIO_F_RING_EVENT_IDX) && 365 ((vsc->sc_dev.dv_cfdata->cf_flags & VIRTIO_CF_NO_EVENT_IDX) || 366 (vsc->sc_child->dv_cfdata->cf_flags & VIRTIO_CF_NO_EVENT_IDX))) { 367 if (guest_feature_names != NULL) 368 printf(" RingEventIdx disabled by UKC"); 369 vsc->sc_driver_features &= ~(VIRTIO_F_RING_EVENT_IDX); 370 } 371 372 bus_space_write_4(sc->sc_iot, sc->sc_ioh, 373 VIRTIO_MMIO_HOST_FEATURES_SEL, 0); 374 host = bus_space_read_4(sc->sc_iot, sc->sc_ioh, 375 VIRTIO_MMIO_HOST_FEATURES); 376 neg = host & vsc->sc_driver_features; 377 #if VIRTIO_DEBUG 378 if (guest_feature_names) 379 virtio_log_features(host, neg, guest_feature_names); 380 #endif 381 bus_space_write_4(sc->sc_iot, sc->sc_ioh, 382 VIRTIO_MMIO_GUEST_FEATURES_SEL, 0); 383 bus_space_write_4(sc->sc_iot, sc->sc_ioh, 384 VIRTIO_MMIO_GUEST_FEATURES, neg); 385 vsc->sc_active_features = neg; 386 if (neg & VIRTIO_F_RING_INDIRECT_DESC) 387 vsc->sc_indirect = 1; 388 else 389 vsc->sc_indirect = 0; 390 391 return 0; 392 } 393 394 /* 395 * Device configuration registers. 396 */ 397 uint8_t 398 virtio_mmio_read_device_config_1(struct virtio_softc *vsc, int index) 399 { 400 struct virtio_mmio_softc *sc = (struct virtio_mmio_softc *)vsc; 401 return bus_space_read_1(sc->sc_iot, sc->sc_ioh, 402 sc->sc_config_offset + index); 403 } 404 405 uint16_t 406 virtio_mmio_read_device_config_2(struct virtio_softc *vsc, int index) 407 { 408 struct virtio_mmio_softc *sc = (struct virtio_mmio_softc *)vsc; 409 return bus_space_read_2(sc->sc_iot, sc->sc_ioh, 410 sc->sc_config_offset + index); 411 } 412 413 uint32_t 414 virtio_mmio_read_device_config_4(struct virtio_softc *vsc, int index) 415 { 416 struct virtio_mmio_softc *sc = (struct virtio_mmio_softc *)vsc; 417 return bus_space_read_4(sc->sc_iot, sc->sc_ioh, 418 sc->sc_config_offset + index); 419 } 420 421 uint64_t 422 virtio_mmio_read_device_config_8(struct virtio_softc *vsc, int index) 423 { 424 struct virtio_mmio_softc *sc = (struct virtio_mmio_softc *)vsc; 425 uint64_t r; 426 427 r = bus_space_read_4(sc->sc_iot, sc->sc_ioh, 428 sc->sc_config_offset + index + sizeof(uint32_t)); 429 r <<= 32; 430 r += bus_space_read_4(sc->sc_iot, sc->sc_ioh, 431 sc->sc_config_offset + index); 432 return r; 433 } 434 435 void 436 virtio_mmio_write_device_config_1(struct virtio_softc *vsc, 437 int index, uint8_t value) 438 { 439 struct virtio_mmio_softc *sc = (struct virtio_mmio_softc *)vsc; 440 bus_space_write_1(sc->sc_iot, sc->sc_ioh, 441 sc->sc_config_offset + index, value); 442 } 443 444 void 445 virtio_mmio_write_device_config_2(struct virtio_softc *vsc, 446 int index, uint16_t value) 447 { 448 struct virtio_mmio_softc *sc = (struct virtio_mmio_softc *)vsc; 449 bus_space_write_2(sc->sc_iot, sc->sc_ioh, 450 sc->sc_config_offset + index, value); 451 } 452 453 void 454 virtio_mmio_write_device_config_4(struct virtio_softc *vsc, 455 int index, uint32_t value) 456 { 457 struct virtio_mmio_softc *sc = (struct virtio_mmio_softc *)vsc; 458 bus_space_write_4(sc->sc_iot, sc->sc_ioh, 459 sc->sc_config_offset + index, value); 460 } 461 462 void 463 virtio_mmio_write_device_config_8(struct virtio_softc *vsc, 464 int index, uint64_t value) 465 { 466 struct virtio_mmio_softc *sc = (struct virtio_mmio_softc *)vsc; 467 bus_space_write_4(sc->sc_iot, sc->sc_ioh, 468 sc->sc_config_offset + index, 469 value & 0xffffffff); 470 bus_space_write_4(sc->sc_iot, sc->sc_ioh, 471 sc->sc_config_offset + index + sizeof(uint32_t), 472 value >> 32); 473 } 474 475 /* 476 * Interrupt handler. 477 */ 478 int 479 virtio_mmio_intr(void *arg) 480 { 481 struct virtio_mmio_softc *sc = arg; 482 struct virtio_softc *vsc = &sc->sc_sc; 483 int isr, r = 0; 484 485 /* check and ack the interrupt */ 486 isr = bus_space_read_4(sc->sc_iot, sc->sc_ioh, 487 VIRTIO_MMIO_INTERRUPT_STATUS); 488 bus_space_write_4(sc->sc_iot, sc->sc_ioh, 489 VIRTIO_MMIO_INTERRUPT_ACK, isr); 490 if ((isr & VIRTIO_MMIO_INT_CONFIG) && 491 (vsc->sc_config_change != NULL)) 492 r = (vsc->sc_config_change)(vsc); 493 if ((isr & VIRTIO_MMIO_INT_VRING)) 494 r |= virtio_check_vqs(vsc); 495 496 return r; 497 } 498 499 void 500 virtio_mmio_kick(struct virtio_softc *vsc, uint16_t idx) 501 { 502 struct virtio_mmio_softc *sc = (struct virtio_mmio_softc *)vsc; 503 bus_space_write_4(sc->sc_iot, sc->sc_ioh, VIRTIO_MMIO_QUEUE_NOTIFY, 504 idx); 505 } 506