1/* $OpenBSD: vpci.c,v 1.36 2024/05/13 01:15:50 jsg Exp $ */ 2/* 3 * Copyright (c) 2008 Mark Kettenis <kettenis@openbsd.org> 4 * 5 * Permission to use, copy, modify, and distribute this software for any 6 * purpose with or without fee is hereby granted, provided that the above 7 * copyright notice and this permission notice appear in all copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 */ 17 18#include <sys/param.h> 19#include <sys/device.h> 20#include <sys/errno.h> 21#include <sys/malloc.h> 22#include <sys/systm.h> 23 24#include <uvm/uvm_extern.h> 25 26#define _SPARC_BUS_DMA_PRIVATE 27#include <machine/bus.h> 28#include <machine/autoconf.h> 29#include <machine/hypervisor.h> 30#include <machine/openfirm.h> 31 32#include <dev/pci/pcivar.h> 33#include <dev/pci/pcireg.h> 34 35#include <sparc64/dev/viommuvar.h> 36#include <sparc64/dev/msivar.h> 37 38#define VPCI_DEFAULT_MSI_EQS 36 39 40extern struct sparc_pci_chipset _sparc_pci_chipset; 41 42struct vpci_msi_msg { 43 uint32_t mm_version; 44 uint8_t mm_reserved[3]; 45 uint8_t mm_type; 46 uint64_t mm_sysino; 47 uint64_t mm_reserved1; 48 uint64_t mm_stick; 49 uint16_t mm_reserved2[3]; 50 uint16_t mm_reqid; 51 uint64_t mm_addr; 52 uint64_t mm_data; 53 uint64_t mm_reserved3; 54}; 55 56struct vpci_range { 57 u_int32_t cspace; 58 u_int32_t child_hi; 59 u_int32_t child_lo; 60 u_int32_t phys_hi; 61 u_int32_t phys_lo; 62 u_int32_t size_hi; 63 u_int32_t size_lo; 64}; 65 66struct vpci_eq { 67 char eq_name[16]; 68 int eq_id; 69 void *eq_ih; 70 struct msi_eq *eq_meq; 71 struct vpci_pbm *eq_pbm; 72 uint8_t *eq_ring; 73 uint64_t eq_mask; 74}; 75 76struct vpci_pbm { 77 struct vpci_softc *vp_sc; 78 uint64_t vp_devhandle; 79 80 struct vpci_range *vp_range; 81 pci_chipset_tag_t vp_pc; 82 int vp_nrange; 83 84 bus_space_tag_t vp_memt; 85 bus_space_tag_t vp_iot; 86 bus_dma_tag_t vp_dmat; 87 struct iommu_state vp_is; 88 89 bus_addr_t vp_msiaddr; 90 int vp_msibase; 91 int vp_msinum; 92 struct intrhand **vp_msi; 93 94 unsigned int vp_neq; 95 struct vpci_eq *vp_eq; 96 97 int vp_flags; 98}; 99 100struct vpci_softc { 101 struct device sc_dv; 102 bus_dma_tag_t sc_dmat; 103 bus_space_tag_t sc_bust; 104 int sc_node; 105}; 106 107uint64_t sun4v_group_sdio_major; 108 109int vpci_match(struct device *, void *, void *); 110void vpci_attach(struct device *, struct device *, void *); 111void vpci_init_iommu(struct vpci_softc *, struct vpci_pbm *); 112void vpci_init_msi(struct vpci_softc *, struct vpci_pbm *); 113int vpci_print(void *, const char *); 114 115pci_chipset_tag_t vpci_alloc_chipset(struct vpci_pbm *, int, 116 pci_chipset_tag_t); 117bus_space_tag_t vpci_alloc_mem_tag(struct vpci_pbm *); 118bus_space_tag_t vpci_alloc_io_tag(struct vpci_pbm *); 119bus_space_tag_t vpci_alloc_bus_tag(struct vpci_pbm *, const char *, 120 int, int, int); 121bus_dma_tag_t vpci_alloc_dma_tag(struct vpci_pbm *); 122 123int vpci_conf_size(pci_chipset_tag_t, pcitag_t); 124pcireg_t vpci_conf_read(pci_chipset_tag_t, pcitag_t, int); 125void vpci_conf_write(pci_chipset_tag_t, pcitag_t, int, pcireg_t); 126 127int vpci_intr_map(struct pci_attach_args *, pci_intr_handle_t *); 128int vpci_intr_nomap(struct pci_attach_args *, pci_intr_handle_t *); 129int vpci_bus_map(bus_space_tag_t, bus_space_tag_t, bus_addr_t, 130 bus_size_t, int, bus_space_handle_t *); 131paddr_t vpci_bus_mmap(bus_space_tag_t, bus_space_tag_t, bus_addr_t, off_t, 132 int, int); 133void *vpci_intr_establish(bus_space_tag_t, bus_space_tag_t, int, int, int, 134 int (*)(void *), void *, const char *); 135void *vpci_intr_establish_cpu(bus_space_tag_t, bus_space_tag_t, int, int, 136 int, struct cpu_info *, int (*)(void *), void *, const char *); 137void vpci_intr_ack(struct intrhand *); 138void vpci_msi_ack(struct intrhand *); 139 140int vpci_msi_eq_intr(void *); 141 142int vpci_dmamap_create(bus_dma_tag_t, bus_dma_tag_t, bus_size_t, int, 143 bus_size_t, bus_size_t, int, bus_dmamap_t *); 144 145int 146vpci_match(struct device *parent, void *match, void *aux) 147{ 148 struct mainbus_attach_args *ma = aux; 149 150 if (strcmp(ma->ma_name, "pci") != 0) 151 return (0); 152 153 return (OF_is_compatible(ma->ma_node, "SUNW,sun4v-pci") || 154 OF_is_compatible(ma->ma_node, "SUNW,sun4v-vpci")); 155} 156 157void 158vpci_attach(struct device *parent, struct device *self, void *aux) 159{ 160 struct vpci_softc *sc = (struct vpci_softc *)self; 161 struct mainbus_attach_args *ma = aux; 162 struct pcibus_attach_args pba; 163 struct vpci_pbm *pbm; 164 int *busranges = NULL, nranges; 165 int virtual, intx; 166 167 sc->sc_dmat = ma->ma_dmatag; 168 sc->sc_bust = ma->ma_bustag; 169 sc->sc_node = ma->ma_node; 170 171 pbm = malloc(sizeof(*pbm), M_DEVBUF, M_NOWAIT | M_ZERO); 172 if (pbm == NULL) 173 panic("vpci: can't alloc vpci pbm"); 174 175 pbm->vp_sc = sc; 176 pbm->vp_devhandle = (ma->ma_reg[0].ur_paddr >> 32) & 0x0fffffff; 177 178 if (getprop(ma->ma_node, "ranges", sizeof(struct vpci_range), 179 &pbm->vp_nrange, (void **)&pbm->vp_range)) 180 panic("vpci: can't get ranges"); 181 182 if (getprop(ma->ma_node, "bus-range", sizeof(int), &nranges, 183 (void **)&busranges)) 184 panic("vpci: can't get bus-range"); 185 186 printf(": bus %d to %d, ", busranges[0], busranges[1]); 187 188 virtual = (OF_getproplen(ma->ma_node, "virtual-root-complex") == 0); 189 intx = (OF_getproplen(ma->ma_node, "pci-intx-not-supported") != 0); 190 191 pbm->vp_memt = vpci_alloc_mem_tag(pbm); 192 pbm->vp_iot = vpci_alloc_io_tag(pbm); 193 pbm->vp_dmat = vpci_alloc_dma_tag(pbm); 194 195 pbm->vp_pc = vpci_alloc_chipset(pbm, ma->ma_node, &_sparc_pci_chipset); 196 pbm->vp_pc->bustag = pbm->vp_memt; 197 198 vpci_init_iommu(sc, pbm); 199 vpci_init_msi(sc, pbm); 200 201 bzero(&pba, sizeof(pba)); 202 pba.pba_busname = "pci"; 203 pba.pba_domain = pci_ndomains++; 204 pba.pba_bus = busranges[0]; 205 pba.pba_pc = pbm->vp_pc; 206 pba.pba_flags = pbm->vp_flags; 207 pba.pba_dmat = pbm->vp_dmat; 208 pba.pba_memt = pbm->vp_memt; 209 pba.pba_iot = pbm->vp_iot; 210 pba.pba_pc->conf_size = vpci_conf_size; 211 pba.pba_pc->conf_read = vpci_conf_read; 212 pba.pba_pc->conf_write = vpci_conf_write; 213 pba.pba_pc->intr_map = (intx ? vpci_intr_map : vpci_intr_nomap); 214 215 free(busranges, M_DEVBUF, 0); 216 217 config_found(&sc->sc_dv, &pba, vpci_print); 218 219 /* 220 * Signal that we're ready to share this root complex with our 221 * guests. 222 */ 223 if (sun4v_group_sdio_major > 0 && !virtual) { 224 int err; 225 226 err = hv_pci_iov_root_configured(pbm->vp_devhandle); 227 if (err != H_EOK) { 228 printf("%s: pci_iov_root_configured: err %x\n", 229 sc->sc_dv.dv_xname, err); 230 } 231 232 } 233} 234 235void 236vpci_init_iommu(struct vpci_softc *sc, struct vpci_pbm *pbm) 237{ 238 struct iommu_state *is = &pbm->vp_is; 239 int tsbsize = 8; 240 u_int32_t iobase = 0x80000000; 241 char *name; 242 243 name = (char *)malloc(32, M_DEVBUF, M_NOWAIT); 244 if (name == NULL) 245 panic("couldn't malloc iommu name"); 246 snprintf(name, 32, "%s dvma", sc->sc_dv.dv_xname); 247 248 viommu_init(name, is, tsbsize, iobase); 249 is->is_devhandle = pbm->vp_devhandle; 250} 251 252void 253vpci_init_msi(struct vpci_softc *sc, struct vpci_pbm *pbm) 254{ 255 u_int32_t msi_addr_range[3]; 256 u_int32_t msi_eq_devino[3] = { 0, 36, 24 }; 257 u_int32_t msi_range[2]; 258 uint64_t sysino; 259 int msis, msi_eq_size, num_eq, unit; 260 struct vpci_eq *eq; 261 int err; 262 CPU_INFO_ITERATOR cii; 263 struct cpu_info *ci; 264 265 /* One eq per cpu, limited by the number of eqs. */ 266 num_eq = min(ncpus, getpropint(sc->sc_node, "#msi-eqs", 36)); 267 if (num_eq == 0) 268 return; 269 270 if (OF_getprop(sc->sc_node, "msi-address-ranges", 271 msi_addr_range, sizeof(msi_addr_range)) <= 0) 272 return; 273 pbm->vp_msiaddr = msi_addr_range[1]; 274 pbm->vp_msiaddr |= ((bus_addr_t)msi_addr_range[0]) << 32; 275 276 msis = getpropint(sc->sc_node, "#msi", 256); 277 pbm->vp_msi = mallocarray(msis, sizeof(*pbm->vp_msi), M_DEVBUF, 278 M_NOWAIT | M_ZERO); 279 if (pbm->vp_msi == NULL) 280 return; 281 282 msi_eq_size = getpropint(sc->sc_node, "msi-eq-size", 256); 283 284 if (OF_getprop(sc->sc_node, "msi-ranges", 285 msi_range, sizeof(msi_range)) <= 0) 286 goto free_table; 287 pbm->vp_msibase = msi_range[0]; 288 289 pbm->vp_neq = num_eq; 290 pbm->vp_eq = mallocarray(num_eq, sizeof(*eq), M_DEVBUF, 291 M_WAITOK | M_ZERO); 292 293 CPU_INFO_FOREACH(cii, ci) { 294 unit = CPU_INFO_UNIT(ci); 295 eq = &pbm->vp_eq[unit]; 296 297 if (unit >= num_eq) 298 continue; 299 300 eq->eq_id = unit; 301 eq->eq_pbm = pbm; 302 snprintf(eq->eq_name, sizeof(eq->eq_name), "%s:%d", 303 sc->sc_dv.dv_xname, unit); 304 305 eq->eq_meq = msi_eq_alloc(sc->sc_dmat, msi_eq_size, 1); 306 if (eq->eq_meq == NULL) 307 goto free_queues; 308 309 err = hv_pci_msiq_conf(pbm->vp_devhandle, unit, 310 eq->eq_meq->meq_map->dm_segs[0].ds_addr, 311 eq->eq_meq->meq_nentries); 312 if (err != H_EOK) 313 goto free_queues; 314 315 eq->eq_mask = (eq->eq_meq->meq_nentries * 316 sizeof(struct vpci_msi_msg)) - 1; 317 318 OF_getprop(sc->sc_node, "msi-eq-to-devino", 319 msi_eq_devino, sizeof(msi_eq_devino)); 320 err = sun4v_intr_devino_to_sysino(pbm->vp_devhandle, 321 msi_eq_devino[2] + unit, &sysino); 322 if (err != H_EOK) 323 goto free_queues; 324 325 eq->eq_ih = vpci_intr_establish_cpu(pbm->vp_memt, pbm->vp_memt, 326 sysino, IPL_HIGH, BUS_INTR_ESTABLISH_MPSAFE, ci, 327 vpci_msi_eq_intr, eq, eq->eq_name); 328 if (eq->eq_ih == NULL) 329 goto free_queues; 330 331 err = hv_pci_msiq_setvalid(pbm->vp_devhandle, unit, 332 PCI_MSIQ_VALID); 333 if (err != H_EOK) { 334 printf("%s: pci_msiq_setvalid(%d): err %d\n", __func__, 335 unit, err); 336 goto free_queues; 337 } 338 339 err = hv_pci_msiq_setstate(pbm->vp_devhandle, unit, 340 PCI_MSIQSTATE_IDLE); 341 if (err != H_EOK) { 342 printf("%s: pci_msiq_setstate(%d): err %d\n", __func__, 343 unit, err); 344 goto free_queues; 345 } 346 } 347 348 pbm->vp_flags |= PCI_FLAGS_MSI_ENABLED; 349 return; 350 351free_queues: 352 CPU_INFO_FOREACH(cii, ci) { 353 unit = CPU_INFO_UNIT(ci); 354 eq = &pbm->vp_eq[unit]; 355 356 if (eq->eq_meq != NULL) 357 msi_eq_free(sc->sc_dmat, eq->eq_meq); 358 359 hv_pci_msiq_conf(pbm->vp_devhandle, unit, 0, 0); 360 } 361 free(pbm->vp_eq, M_DEVBUF, num_eq * sizeof(*eq)); 362free_table: 363 free(pbm->vp_msi, M_DEVBUF, 0); 364} 365 366int 367vpci_print(void *aux, const char *p) 368{ 369 if (p == NULL) 370 return (UNCONF); 371 return (QUIET); 372} 373 374int 375vpci_conf_size(pci_chipset_tag_t pc, pcitag_t tag) 376{ 377 return PCIE_CONFIG_SPACE_SIZE; 378} 379 380pcireg_t 381vpci_conf_read(pci_chipset_tag_t pc, pcitag_t tag, int reg) 382{ 383 struct vpci_pbm *pbm = pc->cookie; 384 uint64_t error_flag, data; 385 386 hv_pci_config_get(pbm->vp_devhandle, PCITAG_OFFSET(tag), reg, 4, 387 &error_flag, &data); 388 389 return (error_flag ? (pcireg_t)~0 : data); 390} 391 392void 393vpci_conf_write(pci_chipset_tag_t pc, pcitag_t tag, int reg, pcireg_t data) 394{ 395 struct vpci_pbm *pbm = pc->cookie; 396 uint64_t error_flag; 397 398 hv_pci_config_put(pbm->vp_devhandle, PCITAG_OFFSET(tag), reg, 4, 399 data, &error_flag); 400} 401 402/* 403 * Bus-specific interrupt mapping 404 */ 405int 406vpci_intr_map(struct pci_attach_args *pa, pci_intr_handle_t *ihp) 407{ 408 struct vpci_pbm *pbm = pa->pa_pc->cookie; 409 uint64_t devhandle = pbm->vp_devhandle; 410 uint64_t devino, sysino; 411 int err; 412 413 /* 414 * If we didn't find a PROM mapping for this interrupt. Try 415 * to construct one ourselves based on the swizzled interrupt 416 * pin. 417 */ 418 if (*ihp == (pci_intr_handle_t)-1 && pa->pa_intrpin != 0) 419 *ihp = pa->pa_intrpin; 420 421 if (*ihp != (pci_intr_handle_t)-1) { 422 devino = INTVEC(*ihp); 423 err = sun4v_intr_devino_to_sysino(devhandle, devino, &sysino); 424 if (err != H_EOK) 425 return (-1); 426 427 *ihp = sysino; 428 return (0); 429 } 430 431 return (-1); 432} 433 434int 435vpci_intr_nomap(struct pci_attach_args *pa, pci_intr_handle_t *ihp) 436{ 437 return (-1); 438} 439 440bus_space_tag_t 441vpci_alloc_mem_tag(struct vpci_pbm *pp) 442{ 443 return (vpci_alloc_bus_tag(pp, "mem", 444 0x02, /* 32-bit mem space (where's the #define???) */ 445 ASI_PRIMARY, ASI_PRIMARY_LITTLE)); 446} 447 448bus_space_tag_t 449vpci_alloc_io_tag(struct vpci_pbm *pp) 450{ 451 return (vpci_alloc_bus_tag(pp, "io", 452 0x01, /* IO space (where's the #define???) */ 453 ASI_PRIMARY, ASI_PRIMARY_LITTLE)); 454} 455 456bus_space_tag_t 457vpci_alloc_bus_tag(struct vpci_pbm *pbm, const char *name, int ss, 458 int asi, int sasi) 459{ 460 struct vpci_softc *sc = pbm->vp_sc; 461 struct sparc_bus_space_tag *bt; 462 463 bt = malloc(sizeof(*bt), M_DEVBUF, M_NOWAIT | M_ZERO); 464 if (bt == NULL) 465 panic("vpci: could not allocate bus tag"); 466 467 snprintf(bt->name, sizeof(bt->name), "%s-pbm_%s(%d/%2.2x)", 468 sc->sc_dv.dv_xname, name, ss, asi); 469 470 bt->cookie = pbm; 471 bt->parent = sc->sc_bust; 472 bt->default_type = ss; 473 bt->asi = asi; 474 bt->sasi = sasi; 475 bt->sparc_bus_map = vpci_bus_map; 476 bt->sparc_bus_mmap = vpci_bus_mmap; 477 bt->sparc_intr_establish = vpci_intr_establish; 478 bt->sparc_intr_establish_cpu = vpci_intr_establish_cpu; 479 return (bt); 480} 481 482bus_dma_tag_t 483vpci_alloc_dma_tag(struct vpci_pbm *pbm) 484{ 485 struct vpci_softc *sc = pbm->vp_sc; 486 bus_dma_tag_t dt, pdt = sc->sc_dmat; 487 488 dt = malloc(sizeof(*dt), M_DEVBUF, M_NOWAIT | M_ZERO); 489 if (dt == NULL) 490 panic("vpci: could not alloc dma tag"); 491 492 dt->_cookie = pbm; 493 dt->_parent = pdt; 494 dt->_dmamap_create = vpci_dmamap_create; 495 dt->_dmamap_destroy = viommu_dvmamap_destroy; 496 dt->_dmamap_load = viommu_dvmamap_load; 497 dt->_dmamap_load_raw = viommu_dvmamap_load_raw; 498 dt->_dmamap_unload = viommu_dvmamap_unload; 499 dt->_dmamap_sync = viommu_dvmamap_sync; 500 dt->_dmamem_alloc = viommu_dvmamem_alloc; 501 dt->_dmamem_free = viommu_dvmamem_free; 502 return (dt); 503} 504 505pci_chipset_tag_t 506vpci_alloc_chipset(struct vpci_pbm *pbm, int node, pci_chipset_tag_t pc) 507{ 508 pci_chipset_tag_t npc; 509 510 npc = malloc(sizeof *npc, M_DEVBUF, M_NOWAIT); 511 if (npc == NULL) 512 panic("vpci: could not allocate pci_chipset_tag_t"); 513 memcpy(npc, pc, sizeof *pc); 514 npc->cookie = pbm; 515 npc->rootnode = node; 516 return (npc); 517} 518 519#define BUS_DMA_FIND_PARENT(t, fn) \ 520 if (t->_parent == NULL) \ 521 panic("null bus_dma parent (" #fn ")"); \ 522 for (t = t->_parent; t->fn == NULL; t = t->_parent) \ 523 if (t->_parent == NULL) \ 524 panic("no bus_dma " #fn " located"); 525 526int 527vpci_dmamap_create(bus_dma_tag_t t, bus_dma_tag_t t0, bus_size_t size, 528 int nsegments, bus_size_t maxsegsz, bus_size_t boundary, int flags, 529 bus_dmamap_t *dmamap) 530{ 531 struct vpci_pbm *vp = t->_cookie; 532 533 return (viommu_dvmamap_create(t, t0, &vp->vp_is, size, nsegments, 534 maxsegsz, boundary, flags, dmamap)); 535} 536 537int 538vpci_bus_map(bus_space_tag_t t, bus_space_tag_t t0, bus_addr_t offset, 539 bus_size_t size, int flags, bus_space_handle_t *hp) 540{ 541 struct vpci_pbm *pbm = t->cookie; 542 int i, ss = t->default_type; 543 544 if (t->parent == 0 || t->parent->sparc_bus_map == 0) 545 panic("vpci_bus_map: invalid parent"); 546 547 if (flags & BUS_SPACE_MAP_PROMADDRESS) { 548 return ((*t->parent->sparc_bus_map) 549 (t, t0, offset, size, flags, hp)); 550 } 551 552 /* Check mappings for 64-bit-address Memory Space if appropriate. */ 553 if (ss == 0x02 && offset > 0xffffffff) 554 ss = 0x03; 555 556 for (i = 0; i < pbm->vp_nrange; i++) { 557 bus_addr_t child, paddr; 558 bus_size_t rsize; 559 560 if (((pbm->vp_range[i].cspace >> 24) & 0x03) != ss) 561 continue; 562 child = pbm->vp_range[i].child_lo; 563 child |= ((bus_addr_t)pbm->vp_range[i].child_hi) << 32; 564 rsize = pbm->vp_range[i].size_lo; 565 rsize |= ((bus_size_t)pbm->vp_range[i].size_hi) << 32; 566 if (offset < child || offset >= child + rsize) 567 continue; 568 569 paddr = pbm->vp_range[i].phys_lo; 570 paddr |= ((bus_addr_t)pbm->vp_range[i].phys_hi) << 32; 571 return ((*t->parent->sparc_bus_map) 572 (t, t0, paddr + offset - child, size, flags, hp)); 573 } 574 575 return (EINVAL); 576} 577 578paddr_t 579vpci_bus_mmap(bus_space_tag_t t, bus_space_tag_t t0, bus_addr_t paddr, 580 off_t off, int prot, int flags) 581{ 582 bus_addr_t offset = paddr; 583 struct vpci_pbm *pbm = t->cookie; 584 int i, ss = t->default_type; 585 586 if (t->parent == 0 || t->parent->sparc_bus_mmap == 0) 587 panic("vpci_bus_mmap: invalid parent"); 588 589 for (i = 0; i < pbm->vp_nrange; i++) { 590 bus_addr_t paddr; 591 592 if (((pbm->vp_range[i].cspace >> 24) & 0x03) != ss) 593 continue; 594 595 paddr = pbm->vp_range[i].phys_lo + offset; 596 paddr |= ((bus_addr_t)pbm->vp_range[i].phys_hi) << 32; 597 return ((*t->parent->sparc_bus_mmap) 598 (t, t0, paddr, off, prot, flags)); 599 } 600 601 return (-1); 602} 603 604void * 605vpci_intr_establish(bus_space_tag_t t, bus_space_tag_t t0, int ihandle, 606 int level, int flags, int (*handler)(void *), void *arg, const char *what) 607{ 608 return (vpci_intr_establish_cpu(t, t0, ihandle, level, flags, NULL, 609 handler, arg, what)); 610} 611 612void * 613vpci_intr_establish_cpu(bus_space_tag_t t, bus_space_tag_t t0, int ihandle, 614 int level, int flags, struct cpu_info *cpu, int (*handler)(void *), 615 void *arg, const char *what) 616{ 617 struct vpci_pbm *pbm = t->cookie; 618 uint64_t devhandle = pbm->vp_devhandle; 619 uint64_t sysino = INTVEC(ihandle); 620 struct intrhand *ih; 621 int err; 622 623 ih = bus_intr_allocate(t0, handler, arg, ihandle, level, 624 NULL, NULL, what); 625 if (ih == NULL) 626 return (NULL); 627 628 if (flags & BUS_INTR_ESTABLISH_MPSAFE) 629 ih->ih_mpsafe = 1; 630 631 if (PCI_INTR_TYPE(ihandle) != PCI_INTR_INTX) { 632 pci_chipset_tag_t pc = pbm->vp_pc; 633 pcitag_t tag = PCI_INTR_TAG(ihandle); 634 int msinum = pbm->vp_msinum++; 635 int msi = pbm->vp_msibase + msinum; 636 int eq = 0; 637 638 evcount_attach(&ih->ih_count, ih->ih_name, NULL); 639 640 ih->ih_ack = vpci_msi_ack; 641 642 pbm->vp_msi[msinum] = ih; 643 ih->ih_number = msinum; 644 645 switch (PCI_INTR_TYPE(ihandle)) { 646 case PCI_INTR_MSI: 647 pci_msi_enable(pc, tag, pbm->vp_msiaddr, msi); 648 break; 649 case PCI_INTR_MSIX: 650 pci_msix_enable(pc, tag, pbm->vp_memt, 651 PCI_INTR_VEC(ihandle), pbm->vp_msiaddr, msi); 652 break; 653 } 654 655 if (cpu != NULL) { 656 /* 657 * For now, if we have fewer eqs than cpus, map 658 * interrupts for the eq-less cpus onto other cpus. 659 */ 660 eq = CPU_INFO_UNIT(cpu) % pbm->vp_neq; 661 } 662 663 err = hv_pci_msi_setmsiq(devhandle, msi, eq, 0); 664 if (err != H_EOK) { 665 printf("%s: pci_msi_setmsiq: err %d\n", __func__, err); 666 return (NULL); 667 } 668 669 err = hv_pci_msi_setvalid(devhandle, msi, PCI_MSI_VALID); 670 if (err != H_EOK) { 671 printf("%s: pci_msi_setvalid: err %d\n", __func__, err); 672 return (NULL); 673 } 674 675 err = hv_pci_msi_setstate(devhandle, msi, PCI_MSISTATE_IDLE); 676 if (err != H_EOK) { 677 printf("%s: pci_msi_setstate: err %d\n", __func__, err); 678 return (NULL); 679 } 680 681 return (ih); 682 } 683 684 err = sun4v_intr_setcookie(devhandle, sysino, (vaddr_t)ih); 685 if (err != H_EOK) 686 return (NULL); 687 688 ih->ih_cpu = cpu; 689 intr_establish(ih); 690 ih->ih_ack = vpci_intr_ack; 691 692 err = sun4v_intr_settarget(devhandle, sysino, ih->ih_cpu->ci_upaid); 693 if (err != H_EOK) 694 return (NULL); 695 696 /* Clear pending interrupts. */ 697 err = sun4v_intr_setstate(devhandle, sysino, INTR_IDLE); 698 if (err != H_EOK) 699 return (NULL); 700 701 err = sun4v_intr_setenabled(devhandle, sysino, INTR_ENABLED); 702 if (err != H_EOK) 703 return (NULL); 704 705 return (ih); 706} 707 708void 709vpci_intr_ack(struct intrhand *ih) 710{ 711 bus_space_tag_t t = ih->ih_bus; 712 struct vpci_pbm *pbm = t->cookie; 713 uint64_t devhandle = pbm->vp_devhandle; 714 uint64_t sysino = INTVEC(ih->ih_number); 715 716 sun4v_intr_setstate(devhandle, sysino, INTR_IDLE); 717} 718 719void 720vpci_msi_ack(struct intrhand *ih) 721{ 722} 723 724int 725vpci_msi_eq_intr(void *arg) 726{ 727 struct vpci_eq *eq = arg; 728 struct vpci_pbm *pbm = eq->eq_pbm; 729 struct vpci_msi_msg *msg; 730 uint64_t devhandle = pbm->vp_devhandle; 731 uint64_t head, tail; 732 struct intrhand *ih; 733 int msinum, msi; 734 int err; 735 736 err = hv_pci_msiq_gethead(devhandle, eq->eq_id, &head); 737 if (err != H_EOK) 738 printf("%s: pci_msiq_gethead(%d): %d\n", __func__, eq->eq_id, 739 err); 740 741 err = hv_pci_msiq_gettail(devhandle, eq->eq_id, &tail); 742 if (err != H_EOK) 743 printf("%s: pci_msiq_gettail(%d): %d\n", __func__, eq->eq_id, 744 err); 745 746 if (head == tail) 747 return (0); 748 749 while (head != tail) { 750 msg = (struct vpci_msi_msg *)(eq->eq_meq->meq_va + head); 751 752 if (msg->mm_type == 0) 753 break; 754 msg->mm_type = 0; 755 756 msi = msg->mm_data; 757 msinum = msi - pbm->vp_msibase; 758 ih = pbm->vp_msi[msinum]; 759 err = hv_pci_msi_setstate(devhandle, msi, PCI_MSISTATE_IDLE); 760 if (err != H_EOK) 761 printf("%s: pci_msi_setstate: %d\n", __func__, err); 762 763 send_softint(ih->ih_pil, ih); 764 765 head += sizeof(struct vpci_msi_msg); 766 head &= eq->eq_mask; 767 } 768 769 err = hv_pci_msiq_sethead(devhandle, eq->eq_id, head); 770 if (err != H_EOK) 771 printf("%s: pci_msiq_sethead(%d): %d\n", __func__, eq->eq_id, 772 err); 773 774 return (1); 775} 776 777const struct cfattach vpci_ca = { 778 sizeof(struct vpci_softc), vpci_match, vpci_attach 779}; 780 781struct cfdriver vpci_cd = { 782 NULL, "vpci", DV_DULL 783}; 784