Re: acpidmar(4): Store PCI domain in softc for segment mapping
hshoexer <[email protected]>
| Newsgroups | gmane.os.openbsd.tech |
|---|---|
| Message-ID | <[email protected]> |
On Wed, Jul 29, 2026 at 11:12:52PM +0200, Mark Kettenis wrote: > > 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); good point! Uupdated diff below. ok? > > 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", > > > > ------------ acpidmar(4): Store PCI domain in softc for segment mapping Ensure we get a valid segement and enforce 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() --- sys/arch/amd64/pci/acpipci.c | 10 +++++++--- sys/dev/acpi/acpidmar.c | 10 +++------- 2 files changed, 10 insertions(+), 10 deletions(-) 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 5771a54ffc9..57581f0e48a 100644 --- a/sys/dev/acpi/acpidmar.c +++ b/sys/dev/acpi/acpidmar.c @@ -2556,11 +2556,7 @@ acpidmar_pci_hook(pci_chipset_tag_t pc, struct pci_attach_args *pa) reg = pci_conf_read(pc, pa->pa_tag, PCI_CLASS_REG); 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; - } + KASSERT(segment >= 0); /* Record PCI-PCI bridge forwarding windows */ bhlc = pci_conf_read(pc, pa->pa_tag, PCI_BHLC_REG); @@ -2584,7 +2580,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 */ @@ -2893,7 +2889,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", -- 2.55.0