Re: acpidmar(4): Store PCI domain in softc for segment mapping
Mark Kettenis <[email protected]> Wed, 29 Jul 2026 23:12:52 +0200
| Newsgroups | gmane.os.openbsd.tech |
|---|---|
| Message-ID | <[email protected]> |
> Date: Tue, 28 Jul 2026 15:39:46 +0200 > From: hshoexer <[email protected]> > > Hi, > > with this change I store the PCI domain in the softc. Later I use > that value when mapping domain to segment. Instead of counting. The way acpipci(4) works we already have a 1:1 mapping between PCI segments and PCI domains. Technically that isn't necessarily correct, but in practice that seems to be the only workable approach. > Also fall back to segment 0, when ACPI did not provide a segment. If APCI doesn't provide a segment, we already set it to 0. This is required by the standard. So... > This actually enforces use of the IOMMU. > > While there: > - tweak printf to use segment instead of PCI domain > - use ACPI provided segment instead of hardcoded 0 in ivhd_showpage() > > ok? > > Take care, > HJ. > > ----------------------------------------------------------------------------- > diff --git a/sys/arch/amd64/pci/acpipci.c b/sys/arch/amd64/pci/acpipci.c > index e3121987654..e5e861662d7 100644 > --- a/sys/arch/amd64/pci/acpipci.c > +++ b/sys/arch/amd64/pci/acpipci.c > @@ -66,6 +66,7 @@ struct acpipci_softc { > char sc_memex_name[32]; > int sc_bus; > uint32_t sc_seg; > + int sc_domain; > }; > > int acpipci_match(struct device *, void *, void *); > @@ -97,15 +98,14 @@ int > acpipci_domain_to_seg(int domain) > { > struct acpipci_softc *sc; > - int i, d = 0; > + int i; > > for (i = 0; i < acpipci_cd.cd_ndevs; i++) { > sc = (struct acpipci_softc *)acpipci_cd.cd_devs[i]; > if (sc == NULL) > continue; > - if (d == domain) > + if (sc->sc_domain == domain) > return sc->sc_seg; > - d++; > } > > return -1; > @@ -147,6 +147,9 @@ acpipci_attach(struct device *parent, struct device *self, void *aux) > aml_evalinteger(sc->sc_acpi, sc->sc_node, "_SEG", 0, NULL, &seg); > sc->sc_seg = seg; > > + /* Assigned when the PCI bus attaches. */ > + sc->sc_domain = -1; > + > if (aml_evalname(sc->sc_acpi, sc->sc_node, "_CRS", 0, NULL, &res)) { > printf(": can't find resources\n"); > > @@ -210,6 +213,7 @@ acpipci_attach_bus(struct device *parent, struct acpipci_softc *sc) > pba.pba_pmemex = sc->sc_memex; > pba.pba_domain = pci_ndomains++; > pba.pba_bus = sc->sc_bus; > + sc->sc_domain = pba.pba_domain; > > /* Enable MSI in ACPI 2.0 and above, unless we're told not to. */ > if (sc->sc_acpi->sc_fadt->hdr.revision >= 2 && > diff --git a/sys/dev/acpi/acpidmar.c b/sys/dev/acpi/acpidmar.c > index 57b90ddb193..cf18265fd09 100644 > --- a/sys/dev/acpi/acpidmar.c > +++ b/sys/dev/acpi/acpidmar.c > @@ -2581,9 +2581,8 @@ acpidmar_pci_hook(pci_chipset_tag_t pc, struct pci_attach_args *pa) > > segment = acpipci_domain_to_seg(pa->pa_domain); > if (segment < 0) { > - DPRINTF(1, "acpidmar: no ACPI segment for pci domain %d\n", > - pa->pa_domain); > - return; > + /* Fall back to segment 0. */ > + segment = 0; > } So it we ever get a -1 here, somethings is really wrong. So I'd probably turn this into: KASSERT(segment >= 0); Otherwise this looks good. I'm still curious to see any x86 AML that actually uses non-zero _SEG numbers. > /* Record PCI-PCI bridge forwarding windows */ > @@ -2608,7 +2607,7 @@ acpidmar_pci_hook(pci_chipset_tag_t pc, struct pci_attach_args *pa) > PCI_SUBCLASS(reg) == PCI_SUBCLASS_BRIDGE_ISA) { > /* For ISA Bridges, map 0-16Mb as 1:1 */ > printf("dmar: %.4x:%.2x:%.2x.%x mapping ISA\n", > - pa->pa_domain, bus, dev, fun); > + segment, bus, dev, fun); > domain_map_pthru(dom, 0x00, 16*1024*1024); > > /* Keep the identity mapped IOVA range out of the allocator */ > @@ -2917,7 +2916,7 @@ ivhd_showpage(struct iommu_softc *iommu, int sid, paddr_t paddr) > if (show > 10) > return; > show++; > - dom = acpidmar_pci_attach(acpidmar_sc, 0, sid, 0); > + dom = acpidmar_pci_attach(acpidmar_sc, iommu->segment, sid, 0); > if (!dom) > return; > printf("DTE: %.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x\n", > >