1 /* $OpenBSD: virtio_mmio.c,v 1.11 2023/05/29 08:13:35 sf 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 old = bus_space_read_4(sc->sc_iot, sc->sc_ioh, 205 VIRTIO_MMIO_STATUS); 206 bus_space_write_4(sc->sc_iot, sc->sc_ioh, VIRTIO_MMIO_STATUS, 207 status|old); 208 } 209 210 int 211 virtio_mmio_match(struct device *parent, void *cfdata, void *aux) 212 { 213 struct fdt_attach_args *faa = aux; 214 215 return OF_is_compatible(faa->fa_node, "virtio,mmio"); 216 } 217 218 void 219 virtio_mmio_attach(struct device *parent, struct device *self, void *aux) 220 { 221 struct fdt_attach_args *faa = aux; 222 struct virtio_mmio_softc *sc = (struct virtio_mmio_softc *)self; 223 struct virtio_softc *vsc = &sc->sc_sc; 224 uint32_t id, magic; 225 226 if (faa->fa_nreg < 1) { 227 printf(": no register data\n"); 228 return; 229 } 230 231 sc->sc_iosize = faa->fa_reg[0].size; 232 sc->sc_iot = faa->fa_iot; 233 sc->sc_dmat = faa->fa_dmat; 234 if (bus_space_map(sc->sc_iot, faa->fa_reg[0].addr, faa->fa_reg[0].size, 235 0, &sc->sc_ioh)) 236 panic("%s: bus_space_map failed!", __func__); 237 238 magic = bus_space_read_4(sc->sc_iot, sc->sc_ioh, 239 VIRTIO_MMIO_MAGIC_VALUE); 240 if (magic != VIRTIO_MMIO_MAGIC) { 241 printf(": wrong magic value 0x%08x; giving up\n", magic); 242 return; 243 } 244 245 sc->sc_version = bus_space_read_4(sc->sc_iot, sc->sc_ioh, 246 VIRTIO_MMIO_VERSION); 247 if (sc->sc_version < 1 || sc->sc_version > 2) { 248 printf(": unknown version 0x%02x; giving up\n", sc->sc_version); 249 return; 250 } 251 252 id = bus_space_read_4(sc->sc_iot, sc->sc_ioh, VIRTIO_MMIO_DEVICE_ID); 253 printf(": Virtio %s Device", virtio_device_string(id)); 254 255 if (sc->sc_version == 1) 256 bus_space_write_4(sc->sc_iot, sc->sc_ioh, 257 VIRTIO_MMIO_GUEST_PAGE_SIZE, PAGE_SIZE); 258 259 printf("\n"); 260 261 /* No device connected. */ 262 if (id == 0) 263 return; 264 265 vsc->sc_ops = &virtio_mmio_ops; 266 vsc->sc_dmat = sc->sc_dmat; 267 sc->sc_config_offset = VIRTIO_MMIO_CONFIG; 268 269 virtio_device_reset(vsc); 270 virtio_mmio_set_status(vsc, VIRTIO_CONFIG_DEVICE_STATUS_ACK); 271 virtio_mmio_set_status(vsc, VIRTIO_CONFIG_DEVICE_STATUS_DRIVER); 272 273 /* XXX: use softc as aux... */ 274 vsc->sc_childdevid = id; 275 vsc->sc_child = NULL; 276 config_found(self, sc, NULL); 277 if (vsc->sc_child == NULL) { 278 printf("%s: no matching child driver; not configured\n", 279 vsc->sc_dev.dv_xname); 280 goto fail_1; 281 } 282 if (vsc->sc_child == VIRTIO_CHILD_ERROR) { 283 printf("%s: virtio configuration failed\n", 284 vsc->sc_dev.dv_xname); 285 goto fail_1; 286 } 287 288 sc->sc_ih = fdt_intr_establish(faa->fa_node, vsc->sc_ipl, 289 virtio_mmio_intr, sc, vsc->sc_dev.dv_xname); 290 if (sc->sc_ih == NULL) { 291 printf("%s: couldn't establish interrupt\n", 292 vsc->sc_dev.dv_xname); 293 goto fail_2; 294 } 295 296 return; 297 298 fail_2: 299 config_detach(vsc->sc_child, 0); 300 fail_1: 301 /* no mmio_mapreg_unmap() or mmio_intr_unmap() */ 302 virtio_set_status(vsc, VIRTIO_CONFIG_DEVICE_STATUS_FAILED); 303 } 304 305 int 306 virtio_mmio_detach(struct device *self, int flags) 307 { 308 struct virtio_mmio_softc *sc = (struct virtio_mmio_softc *)self; 309 struct virtio_softc *vsc = &sc->sc_sc; 310 int r; 311 312 if (vsc->sc_child != 0 && vsc->sc_child != VIRTIO_CHILD_ERROR) { 313 r = config_detach(vsc->sc_child, flags); 314 if (r) 315 return r; 316 } 317 KASSERT(vsc->sc_child == 0 || vsc->sc_child == VIRTIO_CHILD_ERROR); 318 KASSERT(vsc->sc_vqs == 0); 319 fdt_intr_disestablish(sc->sc_ih); 320 sc->sc_ih = 0; 321 if (sc->sc_iosize) 322 bus_space_unmap(sc->sc_iot, sc->sc_ioh, sc->sc_iosize); 323 sc->sc_iosize = 0; 324 325 return 0; 326 } 327 328 /* 329 * Feature negotiation. 330 * Prints available / negotiated features if guest_feature_names != NULL and 331 * VIRTIO_DEBUG is 1 332 */ 333 int 334 virtio_mmio_negotiate_features(struct virtio_softc *vsc, 335 const struct virtio_feature_name *guest_feature_names) 336 { 337 struct virtio_mmio_softc *sc = (struct virtio_mmio_softc *)vsc; 338 uint64_t host, neg; 339 340 vsc->sc_active_features = 0; 341 342 /* 343 * We enable indirect descriptors by default. They can be switched 344 * off by setting bit 1 in the driver flags, see config(8). 345 */ 346 if (!(vsc->sc_dev.dv_cfdata->cf_flags & VIRTIO_CF_NO_INDIRECT) && 347 !(vsc->sc_child->dv_cfdata->cf_flags & VIRTIO_CF_NO_INDIRECT)) { 348 vsc->sc_driver_features |= VIRTIO_F_RING_INDIRECT_DESC; 349 } else if (guest_feature_names != NULL) { 350 printf("RingIndirectDesc disabled by UKC\n"); 351 } 352 /* 353 * The driver must add VIRTIO_F_RING_EVENT_IDX if it supports it. 354 * If it did, check if it is disabled by bit 2 in the driver flags. 355 */ 356 if ((vsc->sc_driver_features & VIRTIO_F_RING_EVENT_IDX) && 357 ((vsc->sc_dev.dv_cfdata->cf_flags & VIRTIO_CF_NO_EVENT_IDX) || 358 (vsc->sc_child->dv_cfdata->cf_flags & VIRTIO_CF_NO_EVENT_IDX))) { 359 if (guest_feature_names != NULL) 360 printf(" RingEventIdx disabled by UKC"); 361 vsc->sc_driver_features &= ~(VIRTIO_F_RING_EVENT_IDX); 362 } 363 364 bus_space_write_4(sc->sc_iot, sc->sc_ioh, 365 VIRTIO_MMIO_HOST_FEATURES_SEL, 0); 366 host = bus_space_read_4(sc->sc_iot, sc->sc_ioh, 367 VIRTIO_MMIO_HOST_FEATURES); 368 neg = host & vsc->sc_driver_features; 369 #if VIRTIO_DEBUG 370 if (guest_feature_names) 371 virtio_log_features(host, neg, guest_feature_names); 372 #endif 373 bus_space_write_4(sc->sc_iot, sc->sc_ioh, 374 VIRTIO_MMIO_GUEST_FEATURES_SEL, 0); 375 bus_space_write_4(sc->sc_iot, sc->sc_ioh, 376 VIRTIO_MMIO_GUEST_FEATURES, neg); 377 vsc->sc_active_features = neg; 378 if (neg & VIRTIO_F_RING_INDIRECT_DESC) 379 vsc->sc_indirect = 1; 380 else 381 vsc->sc_indirect = 0; 382 383 return 0; 384 } 385 386 /* 387 * Device configuration registers. 388 */ 389 uint8_t 390 virtio_mmio_read_device_config_1(struct virtio_softc *vsc, int index) 391 { 392 struct virtio_mmio_softc *sc = (struct virtio_mmio_softc *)vsc; 393 return bus_space_read_1(sc->sc_iot, sc->sc_ioh, 394 sc->sc_config_offset + index); 395 } 396 397 uint16_t 398 virtio_mmio_read_device_config_2(struct virtio_softc *vsc, int index) 399 { 400 struct virtio_mmio_softc *sc = (struct virtio_mmio_softc *)vsc; 401 return bus_space_read_2(sc->sc_iot, sc->sc_ioh, 402 sc->sc_config_offset + index); 403 } 404 405 uint32_t 406 virtio_mmio_read_device_config_4(struct virtio_softc *vsc, int index) 407 { 408 struct virtio_mmio_softc *sc = (struct virtio_mmio_softc *)vsc; 409 return bus_space_read_4(sc->sc_iot, sc->sc_ioh, 410 sc->sc_config_offset + index); 411 } 412 413 uint64_t 414 virtio_mmio_read_device_config_8(struct virtio_softc *vsc, int index) 415 { 416 struct virtio_mmio_softc *sc = (struct virtio_mmio_softc *)vsc; 417 uint64_t r; 418 419 r = bus_space_read_4(sc->sc_iot, sc->sc_ioh, 420 sc->sc_config_offset + index + sizeof(uint32_t)); 421 r <<= 32; 422 r += bus_space_read_4(sc->sc_iot, sc->sc_ioh, 423 sc->sc_config_offset + index); 424 return r; 425 } 426 427 void 428 virtio_mmio_write_device_config_1(struct virtio_softc *vsc, 429 int index, uint8_t value) 430 { 431 struct virtio_mmio_softc *sc = (struct virtio_mmio_softc *)vsc; 432 bus_space_write_1(sc->sc_iot, sc->sc_ioh, 433 sc->sc_config_offset + index, value); 434 } 435 436 void 437 virtio_mmio_write_device_config_2(struct virtio_softc *vsc, 438 int index, uint16_t value) 439 { 440 struct virtio_mmio_softc *sc = (struct virtio_mmio_softc *)vsc; 441 bus_space_write_2(sc->sc_iot, sc->sc_ioh, 442 sc->sc_config_offset + index, value); 443 } 444 445 void 446 virtio_mmio_write_device_config_4(struct virtio_softc *vsc, 447 int index, uint32_t value) 448 { 449 struct virtio_mmio_softc *sc = (struct virtio_mmio_softc *)vsc; 450 bus_space_write_4(sc->sc_iot, sc->sc_ioh, 451 sc->sc_config_offset + index, value); 452 } 453 454 void 455 virtio_mmio_write_device_config_8(struct virtio_softc *vsc, 456 int index, uint64_t value) 457 { 458 struct virtio_mmio_softc *sc = (struct virtio_mmio_softc *)vsc; 459 bus_space_write_4(sc->sc_iot, sc->sc_ioh, 460 sc->sc_config_offset + index, 461 value & 0xffffffff); 462 bus_space_write_4(sc->sc_iot, sc->sc_ioh, 463 sc->sc_config_offset + index + sizeof(uint32_t), 464 value >> 32); 465 } 466 467 /* 468 * Interrupt handler. 469 */ 470 int 471 virtio_mmio_intr(void *arg) 472 { 473 struct virtio_mmio_softc *sc = arg; 474 struct virtio_softc *vsc = &sc->sc_sc; 475 int isr, r = 0; 476 477 /* check and ack the interrupt */ 478 isr = bus_space_read_4(sc->sc_iot, sc->sc_ioh, 479 VIRTIO_MMIO_INTERRUPT_STATUS); 480 bus_space_write_4(sc->sc_iot, sc->sc_ioh, 481 VIRTIO_MMIO_INTERRUPT_ACK, isr); 482 if ((isr & VIRTIO_MMIO_INT_CONFIG) && 483 (vsc->sc_config_change != NULL)) 484 r = (vsc->sc_config_change)(vsc); 485 if ((isr & VIRTIO_MMIO_INT_VRING)) 486 r |= virtio_check_vqs(vsc); 487 488 return r; 489 } 490 491 void 492 virtio_mmio_kick(struct virtio_softc *vsc, uint16_t idx) 493 { 494 struct virtio_mmio_softc *sc = (struct virtio_mmio_softc *)vsc; 495 bus_space_write_4(sc->sc_iot, sc->sc_ioh, VIRTIO_MMIO_QUEUE_NOTIFY, 496 idx); 497 } 498