| @@ -1,14 +1,14 @@ | | | @@ -1,14 +1,14 @@ |
1 | /* $NetBSD: gicv3_its.c,v 1.1 2018/11/09 23:36:24 jmcneill Exp $ */ | | 1 | /* $NetBSD: gicv3_its.c,v 1.2 2018/11/10 11:46:31 jmcneill Exp $ */ |
2 | | | 2 | |
3 | /*- | | 3 | /*- |
4 | * Copyright (c) 2018 The NetBSD Foundation, Inc. | | 4 | * Copyright (c) 2018 The NetBSD Foundation, Inc. |
5 | * All rights reserved. | | 5 | * All rights reserved. |
6 | * | | 6 | * |
7 | * This code is derived from software contributed to The NetBSD Foundation | | 7 | * This code is derived from software contributed to The NetBSD Foundation |
8 | * by Jared McNeill <jmcneill@invisible.ca>. | | 8 | * by Jared McNeill <jmcneill@invisible.ca>. |
9 | * | | 9 | * |
10 | * Redistribution and use in source and binary forms, with or without | | 10 | * Redistribution and use in source and binary forms, with or without |
11 | * modification, are permitted provided that the following conditions | | 11 | * modification, are permitted provided that the following conditions |
12 | * are met: | | 12 | * are met: |
13 | * 1. Redistributions of source code must retain the above copyright | | 13 | * 1. Redistributions of source code must retain the above copyright |
14 | * notice, this list of conditions and the following disclaimer. | | 14 | * notice, this list of conditions and the following disclaimer. |
| @@ -22,27 +22,27 @@ | | | @@ -22,27 +22,27 @@ |
22 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS | | 22 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS |
23 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | | 23 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | | 24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | | 25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | | 26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | | 27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | | 28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
29 | * POSSIBILITY OF SUCH DAMAGE. | | 29 | * POSSIBILITY OF SUCH DAMAGE. |
30 | */ | | 30 | */ |
31 | | | 31 | |
32 | #define _INTR_PRIVATE | | 32 | #define _INTR_PRIVATE |
33 | | | 33 | |
34 | #include <sys/cdefs.h> | | 34 | #include <sys/cdefs.h> |
35 | __KERNEL_RCSID(0, "$NetBSD: gicv3_its.c,v 1.1 2018/11/09 23:36:24 jmcneill Exp $"); | | 35 | __KERNEL_RCSID(0, "$NetBSD: gicv3_its.c,v 1.2 2018/11/10 11:46:31 jmcneill Exp $"); |
36 | | | 36 | |
37 | #include <sys/param.h> | | 37 | #include <sys/param.h> |
38 | #include <sys/kmem.h> | | 38 | #include <sys/kmem.h> |
39 | #include <sys/bus.h> | | 39 | #include <sys/bus.h> |
40 | #include <sys/cpu.h> | | 40 | #include <sys/cpu.h> |
41 | | | 41 | |
42 | #include <uvm/uvm.h> | | 42 | #include <uvm/uvm.h> |
43 | | | 43 | |
44 | #include <dev/pci/pcireg.h> | | 44 | #include <dev/pci/pcireg.h> |
45 | #include <dev/pci/pcivar.h> | | 45 | #include <dev/pci/pcivar.h> |
46 | | | 46 | |
47 | #include <arm/pic/picvar.h> | | 47 | #include <arm/pic/picvar.h> |
48 | #include <arm/cortex/gicv3_its.h> | | 48 | #include <arm/cortex/gicv3_its.h> |
| @@ -146,26 +146,43 @@ gits_command_mapi(struct gicv3_its *its, | | | @@ -146,26 +146,43 @@ gits_command_mapi(struct gicv3_its *its, |
146 | | | 146 | |
147 | /* | | 147 | /* |
148 | * Map the event defined by EventID and DeviceID into an ITT entry with ICID and pINTID = EventID | | 148 | * Map the event defined by EventID and DeviceID into an ITT entry with ICID and pINTID = EventID |
149 | */ | | 149 | */ |
150 | memset(&cmd, 0, sizeof(cmd)); | | 150 | memset(&cmd, 0, sizeof(cmd)); |
151 | cmd.dw[0] = GITS_CMD_MAPI | ((uint64_t)deviceid << 32); | | 151 | cmd.dw[0] = GITS_CMD_MAPI | ((uint64_t)deviceid << 32); |
152 | cmd.dw[1] = eventid; | | 152 | cmd.dw[1] = eventid; |
153 | cmd.dw[2] = icid; | | 153 | cmd.dw[2] = icid; |
154 | | | 154 | |
155 | gits_command(its, &cmd); | | 155 | gits_command(its, &cmd); |
156 | } | | 156 | } |
157 | | | 157 | |
158 | static inline void | | 158 | static inline void |
| | | 159 | gits_command_movi(struct gicv3_its *its, uint32_t deviceid, uint32_t eventid, uint16_t icid) |
| | | 160 | { |
| | | 161 | struct gicv3_its_command cmd; |
| | | 162 | |
| | | 163 | /* |
| | | 164 | * Update the ICID field in the ITT entry for the event defined by DeviceID and |
| | | 165 | * EventID. |
| | | 166 | */ |
| | | 167 | memset(&cmd, 0, sizeof(cmd)); |
| | | 168 | cmd.dw[0] = GITS_CMD_MOVI | ((uint64_t)deviceid << 32); |
| | | 169 | cmd.dw[1] = eventid; |
| | | 170 | cmd.dw[2] = icid; |
| | | 171 | |
| | | 172 | gits_command(its, &cmd); |
| | | 173 | } |
| | | 174 | |
| | | 175 | static inline void |
159 | gits_command_inv(struct gicv3_its *its, uint32_t deviceid, uint32_t eventid) | | 176 | gits_command_inv(struct gicv3_its *its, uint32_t deviceid, uint32_t eventid) |
160 | { | | 177 | { |
161 | struct gicv3_its_command cmd; | | 178 | struct gicv3_its_command cmd; |
162 | | | 179 | |
163 | /* | | 180 | /* |
164 | * Ensure any caching in the redistributors associated with the specified | | 181 | * Ensure any caching in the redistributors associated with the specified |
165 | * EventID is consistent with the LPI configuration tables. | | 182 | * EventID is consistent with the LPI configuration tables. |
166 | */ | | 183 | */ |
167 | memset(&cmd, 0, sizeof(cmd)); | | 184 | memset(&cmd, 0, sizeof(cmd)); |
168 | cmd.dw[0] = GITS_CMD_INV | ((uint64_t)deviceid << 32); | | 185 | cmd.dw[0] = GITS_CMD_INV | ((uint64_t)deviceid << 32); |
169 | cmd.dw[1] = eventid; | | 186 | cmd.dw[1] = eventid; |
170 | | | 187 | |
171 | gits_command(its, &cmd); | | 188 | gits_command(its, &cmd); |
| @@ -369,28 +386,28 @@ gicv3_its_msix_disable(struct gicv3_its | | | @@ -369,28 +386,28 @@ gicv3_its_msix_disable(struct gicv3_its |
369 | if (!pci_get_capability(pc, tag, PCI_CAP_MSIX, &off, NULL)) | | 386 | if (!pci_get_capability(pc, tag, PCI_CAP_MSIX, &off, NULL)) |
370 | panic("gicv3_its_msix_disable: device is not MSI-X-capable"); | | 387 | panic("gicv3_its_msix_disable: device is not MSI-X-capable"); |
371 | | | 388 | |
372 | ctl = pci_conf_read(pc, tag, off + PCI_MSIX_CTL); | | 389 | ctl = pci_conf_read(pc, tag, off + PCI_MSIX_CTL); |
373 | ctl &= ~PCI_MSIX_CTL_ENABLE; | | 390 | ctl &= ~PCI_MSIX_CTL_ENABLE; |
374 | pci_conf_write(pc, tag, off + PCI_MSIX_CTL, ctl); | | 391 | pci_conf_write(pc, tag, off + PCI_MSIX_CTL, ctl); |
375 | } | | 392 | } |
376 | | | 393 | |
377 | static pci_intr_handle_t * | | 394 | static pci_intr_handle_t * |
378 | gicv3_its_msi_alloc(struct arm_pci_msi *msi, int *count, | | 395 | gicv3_its_msi_alloc(struct arm_pci_msi *msi, int *count, |
379 | const struct pci_attach_args *pa, bool exact) | | 396 | const struct pci_attach_args *pa, bool exact) |
380 | { | | 397 | { |
381 | struct gicv3_its * const its = msi->msi_priv; | | 398 | struct gicv3_its * const its = msi->msi_priv; |
| | | 399 | struct cpu_info * const ci = cpu_lookup(0); |
382 | struct gicv3_its_device *dev; | | 400 | struct gicv3_its_device *dev; |
383 | struct cpu_info *ci = curcpu(); /* XXX */ | | | |
384 | pci_intr_handle_t *vectors; | | 401 | pci_intr_handle_t *vectors; |
385 | int n, off; | | 402 | int n, off; |
386 | | | 403 | |
387 | if (!pci_get_capability(pa->pa_pc, pa->pa_tag, PCI_CAP_MSI, &off, NULL)) | | 404 | if (!pci_get_capability(pa->pa_pc, pa->pa_tag, PCI_CAP_MSI, &off, NULL)) |
388 | return NULL; | | 405 | return NULL; |
389 | | | 406 | |
390 | const uint64_t typer = gits_read_8(its, GITS_TYPER); | | 407 | const uint64_t typer = gits_read_8(its, GITS_TYPER); |
391 | const u_int id_bits = __SHIFTOUT(typer, GITS_TYPER_ID_bits) + 1; | | 408 | const u_int id_bits = __SHIFTOUT(typer, GITS_TYPER_ID_bits) + 1; |
392 | if (*count == 0 || *count > (1 << id_bits)) | | 409 | if (*count == 0 || *count > (1 << id_bits)) |
393 | return NULL; | | 410 | return NULL; |
394 | | | 411 | |
395 | const uint32_t devid = gicv3_its_devid(pa->pa_pc, pa->pa_tag); | | 412 | const uint32_t devid = gicv3_its_devid(pa->pa_pc, pa->pa_tag); |
396 | | | 413 | |
| @@ -402,43 +419,48 @@ gicv3_its_msi_alloc(struct arm_pci_msi * | | | @@ -402,43 +419,48 @@ gicv3_its_msi_alloc(struct arm_pci_msi * |
402 | gits_wait(its); | | 419 | gits_wait(its); |
403 | | | 420 | |
404 | vectors = kmem_alloc(sizeof(*vectors) * *count, KM_SLEEP); | | 421 | vectors = kmem_alloc(sizeof(*vectors) * *count, KM_SLEEP); |
405 | for (n = 0; n < *count; n++) { | | 422 | for (n = 0; n < *count; n++) { |
406 | const int lpi = gicv3_its_msi_alloc_lpi(its, pa); | | 423 | const int lpi = gicv3_its_msi_alloc_lpi(its, pa); |
407 | vectors[n] = ARM_PCI_INTR_MSI | | | 424 | vectors[n] = ARM_PCI_INTR_MSI | |
408 | __SHIFTIN(lpi, ARM_PCI_INTR_IRQ) | | | 425 | __SHIFTIN(lpi, ARM_PCI_INTR_IRQ) | |
409 | __SHIFTIN(n, ARM_PCI_INTR_MSI_VEC) | | | 426 | __SHIFTIN(n, ARM_PCI_INTR_MSI_VEC) | |
410 | __SHIFTIN(msi->msi_id, ARM_PCI_INTR_FRAME); | | 427 | __SHIFTIN(msi->msi_id, ARM_PCI_INTR_FRAME); |
411 | | | 428 | |
412 | gicv3_its_msi_enable(its, lpi); | | 429 | gicv3_its_msi_enable(its, lpi); |
413 | | | 430 | |
414 | /* | | 431 | /* |
| | | 432 | * Record target PE |
| | | 433 | */ |
| | | 434 | its->its_targets[lpi - its->its_pic->pic_irqbase] = ci; |
| | | 435 | |
| | | 436 | /* |
415 | * Map event | | 437 | * Map event |
416 | */ | | 438 | */ |
417 | gits_command_mapi(its, devid, lpi, cpu_index(ci)); | | 439 | gits_command_mapi(its, devid, lpi, cpu_index(ci)); |
418 | gits_command_sync(its, its->its_rdbase[cpu_index(ci)]); | | 440 | gits_command_sync(its, its->its_rdbase[cpu_index(ci)]); |
419 | } | | 441 | } |
420 | gits_wait(its); | | 442 | gits_wait(its); |
421 | | | 443 | |
422 | return vectors; | | 444 | return vectors; |
423 | } | | 445 | } |
424 | | | 446 | |
425 | static pci_intr_handle_t * | | 447 | static pci_intr_handle_t * |
426 | gicv3_its_msix_alloc(struct arm_pci_msi *msi, u_int *table_indexes, int *count, | | 448 | gicv3_its_msix_alloc(struct arm_pci_msi *msi, u_int *table_indexes, int *count, |
427 | const struct pci_attach_args *pa, bool exact) | | 449 | const struct pci_attach_args *pa, bool exact) |
428 | { | | 450 | { |
429 | struct gicv3_its * const its = msi->msi_priv; | | 451 | struct gicv3_its * const its = msi->msi_priv; |
| | | 452 | struct cpu_info *ci = cpu_lookup(0); |
430 | struct gicv3_its_device *dev; | | 453 | struct gicv3_its_device *dev; |
431 | struct cpu_info *ci = curcpu(); /* XXX */ | | | |
432 | pci_intr_handle_t *vectors; | | 454 | pci_intr_handle_t *vectors; |
433 | bus_space_tag_t bst; | | 455 | bus_space_tag_t bst; |
434 | bus_space_handle_t bsh; | | 456 | bus_space_handle_t bsh; |
435 | bus_size_t bsz; | | 457 | bus_size_t bsz; |
436 | uint32_t table_offset, table_size; | | 458 | uint32_t table_offset, table_size; |
437 | int n, off, bar, error; | | 459 | int n, off, bar, error; |
438 | pcireg_t tbl; | | 460 | pcireg_t tbl; |
439 | | | 461 | |
440 | if (!pci_get_capability(pa->pa_pc, pa->pa_tag, PCI_CAP_MSIX, &off, NULL)) | | 462 | if (!pci_get_capability(pa->pa_pc, pa->pa_tag, PCI_CAP_MSIX, &off, NULL)) |
441 | return NULL; | | 463 | return NULL; |
442 | | | 464 | |
443 | const uint64_t typer = gits_read_8(its, GITS_TYPER); | | 465 | const uint64_t typer = gits_read_8(its, GITS_TYPER); |
444 | const u_int id_bits = __SHIFTOUT(typer, GITS_TYPER_ID_bits) + 1; | | 466 | const u_int id_bits = __SHIFTOUT(typer, GITS_TYPER_ID_bits) + 1; |
| @@ -469,26 +491,31 @@ gicv3_its_msix_alloc(struct arm_pci_msi | | | @@ -469,26 +491,31 @@ gicv3_its_msix_alloc(struct arm_pci_msi |
469 | | | 491 | |
470 | vectors = kmem_alloc(sizeof(*vectors) * *count, KM_SLEEP); | | 492 | vectors = kmem_alloc(sizeof(*vectors) * *count, KM_SLEEP); |
471 | for (n = 0; n < *count; n++) { | | 493 | for (n = 0; n < *count; n++) { |
472 | const int lpi = gicv3_its_msi_alloc_lpi(its, pa); | | 494 | const int lpi = gicv3_its_msi_alloc_lpi(its, pa); |
473 | const int msix_vec = table_indexes ? table_indexes[n] : n; | | 495 | const int msix_vec = table_indexes ? table_indexes[n] : n; |
474 | vectors[msix_vec] = ARM_PCI_INTR_MSIX | | | 496 | vectors[msix_vec] = ARM_PCI_INTR_MSIX | |
475 | __SHIFTIN(lpi, ARM_PCI_INTR_IRQ) | | | 497 | __SHIFTIN(lpi, ARM_PCI_INTR_IRQ) | |
476 | __SHIFTIN(msix_vec, ARM_PCI_INTR_MSI_VEC) | | | 498 | __SHIFTIN(msix_vec, ARM_PCI_INTR_MSI_VEC) | |
477 | __SHIFTIN(msi->msi_id, ARM_PCI_INTR_FRAME); | | 499 | __SHIFTIN(msi->msi_id, ARM_PCI_INTR_FRAME); |
478 | | | 500 | |
479 | gicv3_its_msix_enable(its, lpi, msix_vec, bst, bsh); | | 501 | gicv3_its_msix_enable(its, lpi, msix_vec, bst, bsh); |
480 | | | 502 | |
481 | /* | | 503 | /* |
| | | 504 | * Record target PE |
| | | 505 | */ |
| | | 506 | its->its_targets[lpi - its->its_pic->pic_irqbase] = ci; |
| | | 507 | |
| | | 508 | /* |
482 | * Map event | | 509 | * Map event |
483 | */ | | 510 | */ |
484 | gits_command_mapi(its, devid, lpi, cpu_index(ci)); | | 511 | gits_command_mapi(its, devid, lpi, cpu_index(ci)); |
485 | gits_command_sync(its, its->its_rdbase[cpu_index(ci)]); | | 512 | gits_command_sync(its, its->its_rdbase[cpu_index(ci)]); |
486 | } | | 513 | } |
487 | gits_wait(its); | | 514 | gits_wait(its); |
488 | | | 515 | |
489 | bus_space_unmap(bst, bsh, bsz); | | 516 | bus_space_unmap(bst, bsh, bsz); |
490 | | | 517 | |
491 | return vectors; | | 518 | return vectors; |
492 | } | | 519 | } |
493 | | | 520 | |
494 | static void * | | 521 | static void * |
| @@ -521,26 +548,27 @@ gicv3_its_msi_intr_release(struct arm_pc | | | @@ -521,26 +548,27 @@ gicv3_its_msi_intr_release(struct arm_pc |
521 | int count) | | 548 | int count) |
522 | { | | 549 | { |
523 | struct gicv3_its * const its = msi->msi_priv; | | 550 | struct gicv3_its * const its = msi->msi_priv; |
524 | int n; | | 551 | int n; |
525 | | | 552 | |
526 | for (n = 0; n < count; n++) { | | 553 | for (n = 0; n < count; n++) { |
527 | const int lpi = __SHIFTOUT(pih[n], ARM_PCI_INTR_IRQ); | | 554 | const int lpi = __SHIFTOUT(pih[n], ARM_PCI_INTR_IRQ); |
528 | KASSERT(lpi >= its->its_pic->pic_irqbase); | | 555 | KASSERT(lpi >= its->its_pic->pic_irqbase); |
529 | if (pih[n] & ARM_PCI_INTR_MSIX) | | 556 | if (pih[n] & ARM_PCI_INTR_MSIX) |
530 | gicv3_its_msix_disable(its, lpi); | | 557 | gicv3_its_msix_disable(its, lpi); |
531 | if (pih[n] & ARM_PCI_INTR_MSI) | | 558 | if (pih[n] & ARM_PCI_INTR_MSI) |
532 | gicv3_its_msi_disable(its, lpi); | | 559 | gicv3_its_msi_disable(its, lpi); |
533 | gicv3_its_msi_free_lpi(its, lpi); | | 560 | gicv3_its_msi_free_lpi(its, lpi); |
| | | 561 | its->its_targets[lpi - its->its_pic->pic_irqbase] = NULL; |
534 | struct intrsource * const is = | | 562 | struct intrsource * const is = |
535 | its->its_pic->pic_sources[lpi - its->its_pic->pic_irqbase]; | | 563 | its->its_pic->pic_sources[lpi - its->its_pic->pic_irqbase]; |
536 | if (is != NULL) | | 564 | if (is != NULL) |
537 | pic_disestablish_source(is); | | 565 | pic_disestablish_source(is); |
538 | } | | 566 | } |
539 | } | | 567 | } |
540 | | | 568 | |
541 | static void | | 569 | static void |
542 | gicv3_its_command_init(struct gicv3_softc *sc, struct gicv3_its *its) | | 570 | gicv3_its_command_init(struct gicv3_softc *sc, struct gicv3_its *its) |
543 | { | | 571 | { |
544 | uint64_t cbaser; | | 572 | uint64_t cbaser; |
545 | | | 573 | |
546 | gicv3_dma_alloc(sc, &its->its_cmd, GITS_COMMANDS_SIZE, GITS_COMMANDS_ALIGN); | | 574 | gicv3_dma_alloc(sc, &its->its_cmd, GITS_COMMANDS_SIZE, GITS_COMMANDS_ALIGN); |
| @@ -648,51 +676,92 @@ gicv3_its_cpu_init(void *priv, struct cp | | | @@ -648,51 +676,92 @@ gicv3_its_cpu_init(void *priv, struct cp |
648 | } else { | | 676 | } else { |
649 | rdbase = (uint64_t)sc->sc_processor_id[cpu_index(ci)] << 16; | | 677 | rdbase = (uint64_t)sc->sc_processor_id[cpu_index(ci)] << 16; |
650 | } | | 678 | } |
651 | its->its_rdbase[cpu_index(ci)] = rdbase; | | 679 | its->its_rdbase[cpu_index(ci)] = rdbase; |
652 | | | 680 | |
653 | /* | | 681 | /* |
654 | * Map collection ID of this CPU's index to this CPU's redistributor. | | 682 | * Map collection ID of this CPU's index to this CPU's redistributor. |
655 | */ | | 683 | */ |
656 | gits_command_mapc(its, cpu_index(ci), rdbase, true); | | 684 | gits_command_mapc(its, cpu_index(ci), rdbase, true); |
657 | gits_command_invall(its, cpu_index(ci)); | | 685 | gits_command_invall(its, cpu_index(ci)); |
658 | gits_wait(its); | | 686 | gits_wait(its); |
659 | } | | 687 | } |
660 | | | 688 | |
| | | 689 | static void |
| | | 690 | gicv3_its_get_affinity(void *priv, size_t irq, kcpuset_t *affinity) |
| | | 691 | { |
| | | 692 | struct gicv3_its * const its = priv; |
| | | 693 | struct cpu_info *ci; |
| | | 694 | |
| | | 695 | kcpuset_zero(affinity); |
| | | 696 | ci = its->its_targets[irq - its->its_pic->pic_irqbase]; |
| | | 697 | if (ci) |
| | | 698 | kcpuset_set(affinity, cpu_index(ci)); |
| | | 699 | } |
| | | 700 | |
| | | 701 | static int |
| | | 702 | gicv3_its_set_affinity(void *priv, size_t irq, const kcpuset_t *affinity) |
| | | 703 | { |
| | | 704 | struct gicv3_its * const its = priv; |
| | | 705 | const struct pci_attach_args *pa; |
| | | 706 | struct cpu_info *ci; |
| | | 707 | |
| | | 708 | const int set = kcpuset_countset(affinity); |
| | | 709 | if (set != 1) |
| | | 710 | return EINVAL; |
| | | 711 | |
| | | 712 | pa = its->its_pa[irq - its->its_pic->pic_irqbase]; |
| | | 713 | if (pa == NULL) |
| | | 714 | return EINVAL; |
| | | 715 | |
| | | 716 | ci = cpu_lookup(kcpuset_ffs(affinity)); |
| | | 717 | |
| | | 718 | const uint32_t devid = gicv3_its_devid(pa->pa_pc, pa->pa_tag); |
| | | 719 | gits_command_movi(its, devid, devid, cpu_index(ci)); |
| | | 720 | gits_command_sync(its, its->its_rdbase[cpu_index(ci)]); |
| | | 721 | |
| | | 722 | its->its_targets[irq - its->its_pic->pic_irqbase] = ci; |
| | | 723 | |
| | | 724 | return 0; |
| | | 725 | } |
| | | 726 | |
661 | int | | 727 | int |
662 | gicv3_its_init(struct gicv3_softc *sc, bus_space_handle_t bsh, | | 728 | gicv3_its_init(struct gicv3_softc *sc, bus_space_handle_t bsh, |
663 | uint64_t its_base, uint32_t its_id) | | 729 | uint64_t its_base, uint32_t its_id) |
664 | { | | 730 | { |
665 | struct gicv3_its *its; | | 731 | struct gicv3_its *its; |
666 | struct arm_pci_msi *msi; | | 732 | struct arm_pci_msi *msi; |
667 | | | 733 | |
668 | const uint64_t typer = bus_space_read_8(sc->sc_bst, bsh, GITS_TYPER); | | 734 | const uint64_t typer = bus_space_read_8(sc->sc_bst, bsh, GITS_TYPER); |
669 | if ((typer & GITS_TYPER_Physical) == 0) | | 735 | if ((typer & GITS_TYPER_Physical) == 0) |
670 | return ENXIO; | | 736 | return ENXIO; |
671 | | | 737 | |
672 | its = kmem_alloc(sizeof(*its), KM_SLEEP); | | 738 | its = kmem_alloc(sizeof(*its), KM_SLEEP); |
673 | its->its_id = its_id; | | 739 | its->its_id = its_id; |
674 | its->its_bst = sc->sc_bst; | | 740 | its->its_bst = sc->sc_bst; |
675 | its->its_bsh = bsh; | | 741 | its->its_bsh = bsh; |
676 | its->its_dmat = sc->sc_dmat; | | 742 | its->its_dmat = sc->sc_dmat; |
677 | its->its_base = its_base; | | 743 | its->its_base = its_base; |
678 | its->its_pic = &sc->sc_lpi; | | 744 | its->its_pic = &sc->sc_lpi; |
679 | KASSERT(its->its_pic->pic_maxsources > 0); | | 745 | KASSERT(its->its_pic->pic_maxsources > 0); |
680 | its->its_pa = kmem_zalloc(sizeof(struct pci_attach_args *) * its->its_pic->pic_maxsources, KM_SLEEP); | | 746 | its->its_pa = kmem_zalloc(sizeof(struct pci_attach_args *) * its->its_pic->pic_maxsources, KM_SLEEP); |
| | | 747 | its->its_targets = kmem_zalloc(sizeof(struct cpu_info *) * its->its_pic->pic_maxsources, KM_SLEEP); |
681 | its->its_gic = sc; | | 748 | its->its_gic = sc; |
682 | its->its_init.func = gicv3_its_cpu_init; | | 749 | its->its_cb.cpu_init = gicv3_its_cpu_init; |
683 | its->its_init.arg = its; | | 750 | its->its_cb.get_affinity = gicv3_its_get_affinity; |
| | | 751 | its->its_cb.set_affinity = gicv3_its_set_affinity; |
| | | 752 | its->its_cb.priv = its; |
684 | LIST_INIT(&its->its_devices); | | 753 | LIST_INIT(&its->its_devices); |
685 | LIST_INSERT_HEAD(&sc->sc_cpu_init, &its->its_init, list); | | 754 | LIST_INSERT_HEAD(&sc->sc_lpi_callbacks, &its->its_cb, list); |
686 | | | 755 | |
687 | gicv3_its_command_init(sc, its); | | 756 | gicv3_its_command_init(sc, its); |
688 | gicv3_its_table_init(sc, its); | | 757 | gicv3_its_table_init(sc, its); |
689 | | | 758 | |
690 | gicv3_its_enable(sc, its); | | 759 | gicv3_its_enable(sc, its); |
691 | | | 760 | |
692 | gicv3_its_cpu_init(its, curcpu()); | | 761 | gicv3_its_cpu_init(its, curcpu()); |
693 | | | 762 | |
694 | msi = &its->its_msi; | | 763 | msi = &its->its_msi; |
695 | msi->msi_dev = sc->sc_dev; | | 764 | msi->msi_dev = sc->sc_dev; |
696 | msi->msi_priv = its; | | 765 | msi->msi_priv = its; |
697 | msi->msi_alloc = gicv3_its_msi_alloc; | | 766 | msi->msi_alloc = gicv3_its_msi_alloc; |
698 | msi->msix_alloc = gicv3_its_msix_alloc; | | 767 | msi->msix_alloc = gicv3_its_msix_alloc; |