Author: kib
Date: Thu Apr 25 08:28:54 2019
New Revision: 346663
URL: https://svnweb.freebsd.org/changeset/base/346663

Log:
  MFC r346352, r346355:
  Correct handling of RMRR during early enumeration stages.

Modified:
  stable/12/sys/x86/iommu/busdma_dmar.c
  stable/12/sys/x86/iommu/intel_ctx.c
  stable/12/sys/x86/iommu/intel_dmar.h
  stable/12/sys/x86/iommu/intel_drv.c
  stable/12/sys/x86/iommu/intel_intrmap.c
  stable/12/sys/x86/iommu/intel_utils.c
Directory Properties:
  stable/12/   (props changed)

Modified: stable/12/sys/x86/iommu/busdma_dmar.c
==============================================================================
--- stable/12/sys/x86/iommu/busdma_dmar.c       Thu Apr 25 08:27:00 2019        
(r346662)
+++ stable/12/sys/x86/iommu/busdma_dmar.c       Thu Apr 25 08:28:54 2019        
(r346663)
@@ -275,7 +275,7 @@ dmar_get_dma_tag(device_t dev, device_t child)
        struct dmar_ctx *ctx;
        bus_dma_tag_t res;
 
-       dmar = dmar_find(child);
+       dmar = dmar_find(child, bootverbose);
        /* Not in scope of any DMAR ? */
        if (dmar == NULL)
                return (NULL);

Modified: stable/12/sys/x86/iommu/intel_ctx.c
==============================================================================
--- stable/12/sys/x86/iommu/intel_ctx.c Thu Apr 25 08:27:00 2019        
(r346662)
+++ stable/12/sys/x86/iommu/intel_ctx.c Thu Apr 25 08:28:54 2019        
(r346663)
@@ -62,6 +62,8 @@ __FBSDID("$FreeBSD$");
 #include <machine/bus.h>
 #include <machine/md_var.h>
 #include <machine/specialreg.h>
+#include <contrib/dev/acpica/include/acpi.h>
+#include <contrib/dev/acpica/include/accommon.h>
 #include <x86/include/busdma_impl.h>
 #include <x86/iommu/intel_reg.h>
 #include <x86/iommu/busdma_dmar.h>
@@ -203,7 +205,9 @@ dmar_flush_for_ctx_entry(struct dmar_unit *dmar, bool 
 }
 
 static int
-domain_init_rmrr(struct dmar_domain *domain, device_t dev)
+domain_init_rmrr(struct dmar_domain *domain, device_t dev, int bus,
+    int slot, int func, int dev_domain, int dev_busno,
+    const void *dev_path, int dev_path_len)
 {
        struct dmar_map_entries_tailq rmrr_entries;
        struct dmar_map_entry *entry, *entry1;
@@ -214,7 +218,8 @@ domain_init_rmrr(struct dmar_domain *domain, device_t 
 
        error = 0;
        TAILQ_INIT(&rmrr_entries);
-       dmar_dev_parse_rmrr(domain, dev, &rmrr_entries);
+       dmar_dev_parse_rmrr(domain, dev_domain, dev_busno, dev_path,
+           dev_path_len, &rmrr_entries);
        TAILQ_FOREACH_SAFE(entry, &rmrr_entries, unroll_link, entry1) {
                /*
                 * VT-d specification requires that the start of an
@@ -227,12 +232,19 @@ domain_init_rmrr(struct dmar_domain *domain, device_t 
                 */
                start = entry->start;
                end = entry->end;
+               if (bootverbose)
+                       printf("dmar%d ctx pci%d:%d:%d RMRR [%#jx, %#jx]\n",
+                           domain->dmar->unit, bus, slot, func,
+                           (uintmax_t)start, (uintmax_t)end);
                entry->start = trunc_page(start);
                entry->end = round_page(end);
                if (entry->start == entry->end) {
                        /* Workaround for some AMI (?) BIOSes */
                        if (bootverbose) {
-                               device_printf(dev, "BIOS bug: dmar%d RMRR "
+                               if (dev != NULL)
+                                       device_printf(dev, "");
+                               printf("pci%d:%d:%d ", bus, slot, func);
+                               printf("BIOS bug: dmar%d RMRR "
                                    "region (%jx, %jx) corrected\n",
                                    domain->dmar->unit, start, end);
                        }
@@ -260,9 +272,13 @@ domain_init_rmrr(struct dmar_domain *domain, device_t 
                        DMAR_UNLOCK(domain->dmar);
                } else {
                        if (error1 != 0) {
-                               device_printf(dev,
+                               if (dev != NULL)
+                                       device_printf(dev, "");
+                               printf("pci%d:%d:%d ", bus, slot, func);
+                               printf(
                            "dmar%d failed to map RMRR region (%jx, %jx) %d\n",
-                                   domain->dmar->unit, start, end, error1);
+                                   domain->dmar->unit, start, end,
+                                   error1);
                                error = error1;
                        }
                        TAILQ_REMOVE(&rmrr_entries, entry, unroll_link);
@@ -404,8 +420,9 @@ dmar_domain_destroy(struct dmar_domain *domain)
        free(domain, M_DMAR_DOMAIN);
 }
 
-struct dmar_ctx *
-dmar_get_ctx_for_dev(struct dmar_unit *dmar, device_t dev, uint16_t rid,
+static struct dmar_ctx *
+dmar_get_ctx_for_dev1(struct dmar_unit *dmar, device_t dev, uint16_t rid,
+    int dev_domain, int dev_busno, const void *dev_path, int dev_path_len,
     bool id_mapped, bool rmrr_init)
 {
        struct dmar_domain *domain, *domain1;
@@ -415,9 +432,15 @@ dmar_get_ctx_for_dev(struct dmar_unit *dmar, device_t 
        int bus, slot, func, error;
        bool enable;
 
-       bus = pci_get_bus(dev);
-       slot = pci_get_slot(dev);
-       func = pci_get_function(dev);
+       if (dev != NULL) {
+               bus = pci_get_bus(dev);
+               slot = pci_get_slot(dev);
+               func = pci_get_function(dev);
+       } else {
+               bus = PCI_RID2BUS(rid);
+               slot = PCI_RID2SLOT(rid);
+               func = PCI_RID2FUNC(rid);
+       }
        enable = false;
        TD_PREP_PINNED_ASSERT;
        DMAR_LOCK(dmar);
@@ -436,7 +459,9 @@ dmar_get_ctx_for_dev(struct dmar_unit *dmar, device_t 
                        return (NULL);
                }
                if (!id_mapped) {
-                       error = domain_init_rmrr(domain1, dev);
+                       error = domain_init_rmrr(domain1, dev, bus,
+                           slot, func, dev_domain, dev_busno, dev_path,
+                           dev_path_len);
                        if (error != 0) {
                                dmar_domain_destroy(domain1);
                                TD_PINNED_ASSERT;
@@ -468,12 +493,14 @@ dmar_get_ctx_for_dev(struct dmar_unit *dmar, device_t 
                                enable = true;
                        LIST_INSERT_HEAD(&dmar->domains, domain, link);
                        ctx_id_entry_init(ctx, ctxp, false);
-                       device_printf(dev,
+                       if (dev != NULL) {
+                               device_printf(dev,
                            "dmar%d pci%d:%d:%d:%d rid %x domain %d mgaw %d "
-                           "agaw %d %s-mapped\n",
-                           dmar->unit, dmar->segment, bus, slot,
-                           func, rid, domain->domain, domain->mgaw,
-                           domain->agaw, id_mapped ? "id" : "re");
+                                   "agaw %d %s-mapped\n",
+                                   dmar->unit, dmar->segment, bus, slot,
+                                   func, rid, domain->domain, domain->mgaw,
+                                   domain->agaw, id_mapped ? "id" : "re");
+                       }
                        dmar_unmap_pgtbl(sf);
                } else {
                        dmar_unmap_pgtbl(sf);
@@ -485,6 +512,8 @@ dmar_get_ctx_for_dev(struct dmar_unit *dmar, device_t 
                }
        } else {
                domain = ctx->domain;
+               if (ctx->ctx_tag.owner == NULL)
+                       ctx->ctx_tag.owner = dev;
                ctx->refs++; /* tag referenced us */
        }
 
@@ -502,7 +531,14 @@ dmar_get_ctx_for_dev(struct dmar_unit *dmar, device_t 
         */
        if (enable && !rmrr_init && (dmar->hw_gcmd & DMAR_GCMD_TE) == 0) {
                error = dmar_enable_translation(dmar);
-               if (error != 0) {
+               if (error == 0) {
+                       if (bootverbose) {
+                               printf("dmar%d: enabled translation\n",
+                                   dmar->unit);
+                       }
+               } else {
+                       printf("dmar%d: enabling translation failed, "
+                           "error %d\n", dmar->unit, error);
                        dmar_free_ctx_locked(dmar, ctx);
                        TD_PINNED_ASSERT;
                        return (NULL);
@@ -511,6 +547,31 @@ dmar_get_ctx_for_dev(struct dmar_unit *dmar, device_t 
        DMAR_UNLOCK(dmar);
        TD_PINNED_ASSERT;
        return (ctx);
+}
+
+struct dmar_ctx *
+dmar_get_ctx_for_dev(struct dmar_unit *dmar, device_t dev, uint16_t rid,
+    bool id_mapped, bool rmrr_init)
+{
+       int dev_domain, dev_path_len, dev_busno;
+
+       dev_domain = pci_get_domain(dev);
+       dev_path_len = dmar_dev_depth(dev);
+       ACPI_DMAR_PCI_PATH dev_path[dev_path_len];
+       dmar_dev_path(dev, &dev_busno, dev_path, dev_path_len);
+       return (dmar_get_ctx_for_dev1(dmar, dev, rid, dev_domain, dev_busno,
+           dev_path, dev_path_len, id_mapped, rmrr_init));
+}
+
+struct dmar_ctx *
+dmar_get_ctx_for_devpath(struct dmar_unit *dmar, uint16_t rid,
+    int dev_domain, int dev_busno,
+    const void *dev_path, int dev_path_len,
+    bool id_mapped, bool rmrr_init)
+{
+
+       return (dmar_get_ctx_for_dev1(dmar, NULL, rid, dev_domain, dev_busno,
+           dev_path, dev_path_len, id_mapped, rmrr_init));
 }
 
 int

Modified: stable/12/sys/x86/iommu/intel_dmar.h
==============================================================================
--- stable/12/sys/x86/iommu/intel_dmar.h        Thu Apr 25 08:27:00 2019        
(r346662)
+++ stable/12/sys/x86/iommu/intel_dmar.h        Thu Apr 25 08:28:54 2019        
(r346663)
@@ -258,7 +258,7 @@ struct dmar_unit {
 #define        DMAR_BARRIER_RMRR       0
 #define        DMAR_BARRIER_USEQ       1
 
-struct dmar_unit *dmar_find(device_t dev);
+struct dmar_unit *dmar_find(device_t dev, bool verbose);
 struct dmar_unit *dmar_find_hpet(device_t dev, uint16_t *rid);
 struct dmar_unit *dmar_find_ioapic(u_int apic_id, uint16_t *rid);
 
@@ -325,10 +325,16 @@ void domain_flush_iotlb_sync(struct dmar_domain *domai
 int domain_alloc_pgtbl(struct dmar_domain *domain);
 void domain_free_pgtbl(struct dmar_domain *domain);
 
+int dmar_dev_depth(device_t child);
+void dmar_dev_path(device_t child, int *busno, void *path1, int depth);
+
 struct dmar_ctx *dmar_instantiate_ctx(struct dmar_unit *dmar, device_t dev,
     bool rmrr);
 struct dmar_ctx *dmar_get_ctx_for_dev(struct dmar_unit *dmar, device_t dev,
     uint16_t rid, bool id_mapped, bool rmrr_init);
+struct dmar_ctx *dmar_get_ctx_for_devpath(struct dmar_unit *dmar, uint16_t rid,
+    int dev_domain, int dev_busno, const void *dev_path, int dev_path_len,
+    bool id_mapped, bool rmrr_init);
 int dmar_move_ctx_to_domain(struct dmar_domain *domain, struct dmar_ctx *ctx);
 void dmar_free_ctx_locked(struct dmar_unit *dmar, struct dmar_ctx *ctx);
 void dmar_free_ctx(struct dmar_ctx *ctx);
@@ -360,7 +366,8 @@ int dmar_gas_map_region(struct dmar_domain *domain,
 int dmar_gas_reserve_region(struct dmar_domain *domain, dmar_gaddr_t start,
     dmar_gaddr_t end);
 
-void dmar_dev_parse_rmrr(struct dmar_domain *domain, device_t dev,
+void dmar_dev_parse_rmrr(struct dmar_domain *domain, int dev_domain,
+    int dev_busno, const void *dev_path, int dev_path_len,
     struct dmar_map_entries_tailq *rmrr_entries);
 int dmar_instantiate_rmrr_ctxs(struct dmar_unit *dmar);
 
@@ -382,7 +389,6 @@ void dmar_fini_irt(struct dmar_unit *unit);
 extern dmar_haddr_t dmar_high;
 extern int haw;
 extern int dmar_tbl_pagecnt;
-extern int dmar_match_verbose;
 extern int dmar_batch_coalesce;
 extern int dmar_check_free;
 

Modified: stable/12/sys/x86/iommu/intel_drv.c
==============================================================================
--- stable/12/sys/x86/iommu/intel_drv.c Thu Apr 25 08:27:00 2019        
(r346662)
+++ stable/12/sys/x86/iommu/intel_drv.c Thu Apr 25 08:28:54 2019        
(r346663)
@@ -54,6 +54,7 @@ __FBSDID("$FreeBSD$");
 #include <sys/tree.h>
 #include <sys/vmem.h>
 #include <machine/bus.h>
+#include <machine/pci_cfgreg.h>
 #include <contrib/dev/acpica/include/acpi.h>
 #include <contrib/dev/acpica/include/accommon.h>
 #include <dev/acpica/acpivar.h>
@@ -176,7 +177,6 @@ dmar_identify(driver_t *driver, device_t parent)
 #ifdef INVARIANTS
        TUNABLE_INT_FETCH("hw.dmar.check_free", &dmar_check_free);
 #endif
-       TUNABLE_INT_FETCH("hw.dmar.match_verbose", &dmar_match_verbose);
        status = AcpiGetTable(ACPI_SIG_DMAR, 1, (ACPI_TABLE_HEADER **)&dmartbl);
        if (ACPI_FAILURE(status))
                return;
@@ -595,21 +595,20 @@ DRIVER_MODULE(dmar, acpi, dmar_driver, dmar_devclass, 
 MODULE_DEPEND(dmar, acpi, 1, 1, 1);
 
 static void
-dmar_print_path(device_t dev, const char *banner, int busno, int depth,
-    const ACPI_DMAR_PCI_PATH *path)
+dmar_print_path(int busno, int depth, const ACPI_DMAR_PCI_PATH *path)
 {
        int i;
 
-       device_printf(dev, "%s [%d, ", banner, busno);
+       printf("[%d, ", busno);
        for (i = 0; i < depth; i++) {
                if (i != 0)
                        printf(", ");
                printf("(%d, %d)", path[i].Device, path[i].Function);
        }
-       printf("]\n");
+       printf("]");
 }
 
-static int
+int
 dmar_dev_depth(device_t child)
 {
        devclass_t pci_class;
@@ -627,13 +626,15 @@ dmar_dev_depth(device_t child)
        }
 }
 
-static void
-dmar_dev_path(device_t child, int *busno, ACPI_DMAR_PCI_PATH *path, int depth)
+void
+dmar_dev_path(device_t child, int *busno, void *path1, int depth)
 {
        devclass_t pci_class;
        device_t bus, pcib;
+       ACPI_DMAR_PCI_PATH *path;
 
        pci_class = devclass_find("pci");
+       path = path1;
        for (depth--; depth != -1; depth--) {
                path[depth].Device = pci_get_slot(child);
                path[depth].Function = pci_get_function(child);
@@ -673,14 +674,14 @@ dmar_match_pathes(int busno1, const ACPI_DMAR_PCI_PATH
 }
 
 static int
-dmar_match_devscope(ACPI_DMAR_DEVICE_SCOPE *devscope, device_t dev,
-    int dev_busno, const ACPI_DMAR_PCI_PATH *dev_path, int dev_path_len)
+dmar_match_devscope(ACPI_DMAR_DEVICE_SCOPE *devscope, int dev_busno,
+    const ACPI_DMAR_PCI_PATH *dev_path, int dev_path_len)
 {
        ACPI_DMAR_PCI_PATH *path;
        int path_len;
 
        if (devscope->Length < sizeof(*devscope)) {
-               printf("dmar_find: corrupted DMAR table, dl %d\n",
+               printf("dmar_match_devscope: corrupted DMAR table, dl %d\n",
                    devscope->Length);
                return (-1);
        }
@@ -689,99 +690,112 @@ dmar_match_devscope(ACPI_DMAR_DEVICE_SCOPE *devscope, 
                return (0);
        path_len = devscope->Length - sizeof(*devscope);
        if (path_len % 2 != 0) {
-               printf("dmar_find_bsf: corrupted DMAR table, dl %d\n",
+               printf("dmar_match_devscope: corrupted DMAR table, dl %d\n",
                    devscope->Length);
                return (-1);
        }
        path_len /= 2;
        path = (ACPI_DMAR_PCI_PATH *)(devscope + 1);
        if (path_len == 0) {
-               printf("dmar_find: corrupted DMAR table, dl %d\n",
+               printf("dmar_match_devscope: corrupted DMAR table, dl %d\n",
                    devscope->Length);
                return (-1);
        }
-       if (dmar_match_verbose)
-               dmar_print_path(dev, "DMAR", devscope->Bus, path_len, path);
 
        return (dmar_match_pathes(devscope->Bus, path, path_len, dev_busno,
            dev_path, dev_path_len, devscope->EntryType));
 }
 
-struct dmar_unit *
-dmar_find(device_t dev)
+static bool
+dmar_match_by_path(struct dmar_unit *unit, int dev_domain, int dev_busno,
+    const ACPI_DMAR_PCI_PATH *dev_path, int dev_path_len, const char **banner)
 {
-       device_t dmar_dev;
        ACPI_DMAR_HARDWARE_UNIT *dmarh;
        ACPI_DMAR_DEVICE_SCOPE *devscope;
        char *ptr, *ptrend;
-       int i, match, dev_domain, dev_busno, dev_path_len;
+       int match;
 
+       dmarh = dmar_find_by_index(unit->unit);
+       if (dmarh == NULL)
+               return (false);
+       if (dmarh->Segment != dev_domain)
+               return (false);
+       if ((dmarh->Flags & ACPI_DMAR_INCLUDE_ALL) != 0) {
+               if (banner != NULL)
+                       *banner = "INCLUDE_ALL";
+               return (true);
+       }
+       ptr = (char *)dmarh + sizeof(*dmarh);
+       ptrend = (char *)dmarh + dmarh->Header.Length;
+       while (ptr < ptrend) {
+               devscope = (ACPI_DMAR_DEVICE_SCOPE *)ptr;
+               ptr += devscope->Length;
+               match = dmar_match_devscope(devscope, dev_busno, dev_path,
+                   dev_path_len);
+               if (match == -1)
+                       return (false);
+               if (match == 1) {
+                       if (banner != NULL)
+                               *banner = "specific match";
+                       return (true);
+               }
+       }
+       return (false);
+}
+
+static struct dmar_unit *
+dmar_find_by_scope(int dev_domain, int dev_busno,
+    const ACPI_DMAR_PCI_PATH *dev_path, int dev_path_len)
+{
+       struct dmar_unit *unit;
+       int i;
+
+       for (i = 0; i < dmar_devcnt; i++) {
+               if (dmar_devs[i] == NULL)
+                       continue;
+               unit = device_get_softc(dmar_devs[i]);
+               if (dmar_match_by_path(unit, dev_domain, dev_busno, dev_path,
+                   dev_path_len, NULL))
+                       return (unit);
+       }
+       return (NULL);
+}
+
+struct dmar_unit *
+dmar_find(device_t dev, bool verbose)
+{
+       device_t dmar_dev;
+       struct dmar_unit *unit;
+       const char *banner;
+       int i, dev_domain, dev_busno, dev_path_len;
+
        dmar_dev = NULL;
        dev_domain = pci_get_domain(dev);
        dev_path_len = dmar_dev_depth(dev);
        ACPI_DMAR_PCI_PATH dev_path[dev_path_len];
        dmar_dev_path(dev, &dev_busno, dev_path, dev_path_len);
-       if (dmar_match_verbose)
-               dmar_print_path(dev, "PCI", dev_busno, dev_path_len, dev_path);
+       banner = "";
 
        for (i = 0; i < dmar_devcnt; i++) {
                if (dmar_devs[i] == NULL)
                        continue;
-               dmarh = dmar_find_by_index(i);
-               if (dmarh == NULL)
-                       continue;
-               if (dmarh->Segment != dev_domain)
-                       continue;
-               if ((dmarh->Flags & ACPI_DMAR_INCLUDE_ALL) != 0) {
-                       dmar_dev = dmar_devs[i];
-                       if (dmar_match_verbose) {
-                               device_printf(dev,
-                                   "pci%d:%d:%d:%d matched dmar%d 
INCLUDE_ALL\n",
-                                   dev_domain, pci_get_bus(dev),
-                                   pci_get_slot(dev),
-                                   pci_get_function(dev),
-                                   ((struct dmar_unit *)device_get_softc(
-                                   dmar_dev))->unit);
-                       }
-                       goto found;
-               }
-               ptr = (char *)dmarh + sizeof(*dmarh);
-               ptrend = (char *)dmarh + dmarh->Header.Length;
-               for (;;) {
-                       if (ptr >= ptrend)
-                               break;
-                       devscope = (ACPI_DMAR_DEVICE_SCOPE *)ptr;
-                       ptr += devscope->Length;
-                       if (dmar_match_verbose) {
-                               device_printf(dev,
-                                   "pci%d:%d:%d:%d matching dmar%d\n",
-                                   dev_domain, pci_get_bus(dev),
-                                   pci_get_slot(dev),
-                                   pci_get_function(dev),
-                                   ((struct dmar_unit *)device_get_softc(
-                                   dmar_devs[i]))->unit);
-                       }
-                       match = dmar_match_devscope(devscope, dev, dev_busno,
-                           dev_path, dev_path_len);
-                       if (dmar_match_verbose) {
-                               if (match == -1)
-                                       printf("table error\n");
-                               else if (match == 0)
-                                       printf("not matched\n");
-                               else
-                                       printf("matched\n");
-                       }
-                       if (match == -1)
-                               return (NULL);
-                       else if (match == 1) {
-                               dmar_dev = dmar_devs[i];
-                               goto found;
-                       }
-               }
+               unit = device_get_softc(dmar_devs[i]);
+               if (dmar_match_by_path(unit, dev_domain, dev_busno,
+                   dev_path, dev_path_len, &banner))
+                       break;
        }
-       return (NULL);
-found:
-       return (device_get_softc(dmar_dev));
+       if (i == dmar_devcnt)
+               return (NULL);
+
+       if (verbose) {
+               device_printf(dev, "pci%d:%d:%d:%d matched dmar%d by %s",
+                   dev_domain, pci_get_bus(dev), pci_get_slot(dev),
+                   pci_get_function(dev), unit->unit, banner);
+               printf(" scope path ");
+               dmar_print_path(dev_busno, dev_path_len, dev_path);
+               printf("\n");
+       }
+       return (unit);
 }
 
 static struct dmar_unit *
@@ -865,10 +879,9 @@ dmar_find_ioapic(u_int apic_id, uint16_t *rid)
 
 struct rmrr_iter_args {
        struct dmar_domain *domain;
-       device_t dev;
        int dev_domain;
        int dev_busno;
-       ACPI_DMAR_PCI_PATH *dev_path;
+       const ACPI_DMAR_PCI_PATH *dev_path;
        int dev_path_len;
        struct dmar_map_entries_tailq *rmrr_entries;
 };
@@ -888,12 +901,6 @@ dmar_rmrr_iter(ACPI_DMAR_HEADER *dmarh, void *arg)
 
        ria = arg;
        resmem = (ACPI_DMAR_RESERVED_MEMORY *)dmarh;
-       if (dmar_match_verbose) {
-               printf("RMRR [%jx,%jx] segment %d\n",
-                   (uintmax_t)resmem->BaseAddress,
-                   (uintmax_t)resmem->EndAddress,
-                   resmem->Segment);
-       }
        if (resmem->Segment != ria->dev_domain)
                return (1);
 
@@ -904,11 +911,9 @@ dmar_rmrr_iter(ACPI_DMAR_HEADER *dmarh, void *arg)
                        break;
                devscope = (ACPI_DMAR_DEVICE_SCOPE *)ptr;
                ptr += devscope->Length;
-               match = dmar_match_devscope(devscope, ria->dev, ria->dev_busno,
+               match = dmar_match_devscope(devscope, ria->dev_busno,
                    ria->dev_path, ria->dev_path_len);
                if (match == 1) {
-                       if (dmar_match_verbose)
-                               printf("matched\n");
                        entry = dmar_gas_alloc_entry(ria->domain,
                            DMAR_PGF_WAITOK);
                        entry->start = resmem->BaseAddress;
@@ -916,8 +921,6 @@ dmar_rmrr_iter(ACPI_DMAR_HEADER *dmarh, void *arg)
                        entry->end = resmem->EndAddress;
                        TAILQ_INSERT_TAIL(ria->rmrr_entries, entry,
                            unroll_link);
-               } else if (dmar_match_verbose) {
-                       printf("not matched, err %d\n", match);
                }
        }
 
@@ -925,25 +928,17 @@ dmar_rmrr_iter(ACPI_DMAR_HEADER *dmarh, void *arg)
 }
 
 void
-dmar_dev_parse_rmrr(struct dmar_domain *domain, device_t dev,
+dmar_dev_parse_rmrr(struct dmar_domain *domain, int dev_domain, int dev_busno,
+    const void *dev_path, int dev_path_len,
     struct dmar_map_entries_tailq *rmrr_entries)
 {
        struct rmrr_iter_args ria;
 
-       ria.dev_domain = pci_get_domain(dev);
-       ria.dev_path_len = dmar_dev_depth(dev);
-       ACPI_DMAR_PCI_PATH dev_path[ria.dev_path_len];
-       dmar_dev_path(dev, &ria.dev_busno, dev_path, ria.dev_path_len);
-
-       if (dmar_match_verbose) {
-               device_printf(dev, "parsing RMRR entries for ");
-               dmar_print_path(dev, "PCI", ria.dev_busno, ria.dev_path_len,
-                   dev_path);
-       }
-
        ria.domain = domain;
-       ria.dev = dev;
-       ria.dev_path = dev_path;
+       ria.dev_domain = dev_domain;
+       ria.dev_busno = dev_busno;
+       ria.dev_path = (const ACPI_DMAR_PCI_PATH *)dev_path;
+       ria.dev_path_len = dev_path_len;
        ria.rmrr_entries = rmrr_entries;
        dmar_iterate_tbl(dmar_rmrr_iter, &ria);
 }
@@ -954,28 +949,22 @@ struct inst_rmrr_iter_args {
 
 static device_t
 dmar_path_dev(int segment, int path_len, int busno,
-    const ACPI_DMAR_PCI_PATH *path)
+    const ACPI_DMAR_PCI_PATH *path, uint16_t *rid)
 {
-       devclass_t pci_class;
-       device_t bus, pcib, dev;
+       device_t dev;
        int i;
 
-       pci_class = devclass_find("pci");
        dev = NULL;
-       for (i = 0; i < path_len; i++, path++) {
+       for (i = 0; i < path_len; i++) {
                dev = pci_find_dbsf(segment, busno, path->Device,
                    path->Function);
-               if (dev == NULL)
-                       break;
                if (i != path_len - 1) {
-                       bus = device_get_parent(dev);
-                       pcib = device_get_parent(bus);
-                       if (device_get_devclass(device_get_parent(pcib)) !=
-                           pci_class)
-                               return (NULL);
+                       busno = pci_cfgregread(busno, path->Device,
+                           path->Function, PCIR_SECBUS_1, 1);
+                       path++;
                }
-               busno = pcib_get_bus(dev);
        }
+       *rid = PCI_RID(busno, path->Device, path->Function);
        return (dev);
 }
 
@@ -986,21 +975,19 @@ dmar_inst_rmrr_iter(ACPI_DMAR_HEADER *dmarh, void *arg
        const ACPI_DMAR_DEVICE_SCOPE *devscope;
        struct inst_rmrr_iter_args *iria;
        const char *ptr, *ptrend;
-       struct dmar_unit *dev_dmar;
        device_t dev;
+       struct dmar_unit *unit;
+       int dev_path_len;
+       uint16_t rid;
 
+       iria = arg;
+
        if (dmarh->Type != ACPI_DMAR_TYPE_RESERVED_MEMORY)
                return (1);
 
-       iria = arg;
        resmem = (ACPI_DMAR_RESERVED_MEMORY *)dmarh;
        if (resmem->Segment != iria->dmar->segment)
                return (1);
-       if (dmar_match_verbose) {
-               printf("dmar%d: RMRR [%jx,%jx]\n", iria->dmar->unit,
-                   (uintmax_t)resmem->BaseAddress,
-                   (uintmax_t)resmem->EndAddress);
-       }
 
        ptr = (const char *)resmem + sizeof(*resmem);
        ptrend = (const char *)resmem + resmem->Header.Length;
@@ -1012,31 +999,40 @@ dmar_inst_rmrr_iter(ACPI_DMAR_HEADER *dmarh, void *arg
                /* XXXKIB bridge */
                if (devscope->EntryType != ACPI_DMAR_SCOPE_TYPE_ENDPOINT)
                        continue;
-               if (dmar_match_verbose) {
-                       dmar_print_path(iria->dmar->dev, "RMRR scope",
-                           devscope->Bus, (devscope->Length -
-                           sizeof(ACPI_DMAR_DEVICE_SCOPE)) / 2,
-                           (const ACPI_DMAR_PCI_PATH *)(devscope + 1));
-               }
-               dev = dmar_path_dev(resmem->Segment, (devscope->Length -
-                   sizeof(ACPI_DMAR_DEVICE_SCOPE)) / 2, devscope->Bus,
-                   (const ACPI_DMAR_PCI_PATH *)(devscope + 1));
+               rid = 0;
+               dev_path_len = (devscope->Length -
+                   sizeof(ACPI_DMAR_DEVICE_SCOPE)) / 2;
+               dev = dmar_path_dev(resmem->Segment, dev_path_len,
+                   devscope->Bus,
+                   (const ACPI_DMAR_PCI_PATH *)(devscope + 1), &rid);
                if (dev == NULL) {
-                       if (dmar_match_verbose)
-                               printf("null dev\n");
-                       continue;
-               }
-               dev_dmar = dmar_find(dev);
-               if (dev_dmar != iria->dmar) {
-                       if (dmar_match_verbose) {
-                               printf("dmar%d matched, skipping\n",
-                                   dev_dmar->unit);
+                       if (bootverbose) {
+                               printf("dmar%d no dev found for RMRR "
+                                   "[%#jx, %#jx] rid %#x scope path ",
+                                    iria->dmar->unit,
+                                    (uintmax_t)resmem->BaseAddress,
+                                    (uintmax_t)resmem->EndAddress,
+                                    rid);
+                               dmar_print_path(devscope->Bus, dev_path_len,
+                                   (const ACPI_DMAR_PCI_PATH *)(devscope + 1));
+                               printf("\n");
                        }
-                       continue;
+                       unit = dmar_find_by_scope(resmem->Segment,
+                           devscope->Bus,
+                           (const ACPI_DMAR_PCI_PATH *)(devscope + 1),
+                           dev_path_len);
+                       if (iria->dmar != unit)
+                               continue;
+                       dmar_get_ctx_for_devpath(iria->dmar, rid,
+                           resmem->Segment, devscope->Bus, 
+                           (const ACPI_DMAR_PCI_PATH *)(devscope + 1),
+                           dev_path_len, false, true);
+               } else {
+                       unit = dmar_find(dev, false);
+                       if (iria->dmar != unit)
+                               continue;
+                       dmar_instantiate_ctx(iria->dmar, dev, true);
                }
-               if (dmar_match_verbose)
-                       printf("matched, instantiating RMRR context\n");
-               dmar_instantiate_ctx(iria->dmar, dev, true);
        }
 
        return (1);
@@ -1057,8 +1053,6 @@ dmar_instantiate_rmrr_ctxs(struct dmar_unit *dmar)
 
        error = 0;
        iria.dmar = dmar;
-       if (dmar_match_verbose)
-               printf("dmar%d: instantiating RMRR contexts\n", dmar->unit);
        dmar_iterate_tbl(dmar_inst_rmrr_iter, &iria);
        DMAR_LOCK(dmar);
        if (!LIST_EMPTY(&dmar->domains)) {
@@ -1066,6 +1060,15 @@ dmar_instantiate_rmrr_ctxs(struct dmar_unit *dmar)
            ("dmar%d: RMRR not handled but translation is already enabled",
                    dmar->unit));
                error = dmar_enable_translation(dmar);
+               if (bootverbose) {
+                       if (error == 0) {
+                               printf("dmar%d: enabled translation\n",
+                                   dmar->unit);
+                       } else {
+                               printf("dmar%d: enabling translation failed, "
+                                   "error %d\n", dmar->unit, error);
+                       }
+               }
        }
        dmar_barrier_exit(dmar, DMAR_BARRIER_RMRR);
        return (error);

Modified: stable/12/sys/x86/iommu/intel_intrmap.c
==============================================================================
--- stable/12/sys/x86/iommu/intel_intrmap.c     Thu Apr 25 08:27:00 2019        
(r346662)
+++ stable/12/sys/x86/iommu/intel_intrmap.c     Thu Apr 25 08:28:54 2019        
(r346663)
@@ -251,7 +251,7 @@ dmar_ir_find(device_t src, uint16_t *rid, int *is_dmar
        } else if (src_class == devclass_find("hpet")) {
                unit = dmar_find_hpet(src, rid);
        } else {
-               unit = dmar_find(src);
+               unit = dmar_find(src, bootverbose);
                if (unit != NULL && rid != NULL)
                        dmar_get_requester(src, rid);
        }

Modified: stable/12/sys/x86/iommu/intel_utils.c
==============================================================================
--- stable/12/sys/x86/iommu/intel_utils.c       Thu Apr 25 08:27:00 2019        
(r346662)
+++ stable/12/sys/x86/iommu/intel_utils.c       Thu Apr 25 08:28:54 2019        
(r346663)
@@ -614,7 +614,6 @@ dmar_barrier_exit(struct dmar_unit *dmar, u_int barrie
        DMAR_UNLOCK(dmar);
 }
 
-int dmar_match_verbose;
 int dmar_batch_coalesce = 100;
 struct timespec dmar_hw_timeout = {
        .tv_sec = 0,
@@ -658,9 +657,6 @@ static SYSCTL_NODE(_hw, OID_AUTO, dmar, CTLFLAG_RD, NU
 SYSCTL_INT(_hw_dmar, OID_AUTO, tbl_pagecnt, CTLFLAG_RD,
     &dmar_tbl_pagecnt, 0,
     "Count of pages used for DMAR pagetables");
-SYSCTL_INT(_hw_dmar, OID_AUTO, match_verbose, CTLFLAG_RWTUN,
-    &dmar_match_verbose, 0,
-    "Verbose matching of the PCI devices to DMAR paths");
 SYSCTL_INT(_hw_dmar, OID_AUTO, batch_coalesce, CTLFLAG_RWTUN,
     &dmar_batch_coalesce, 0,
     "Number of qi batches between interrupt");
_______________________________________________
[email protected] mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "[email protected]"

Reply via email to