Date: Thu, 25 Apr 2019 08:28:54 +0000 (UTC) From: Konstantin Belousov <kib@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-12@freebsd.org Subject: svn commit: r346663 - stable/12/sys/x86/iommu Message-ID: <201904250828.x3P8SsJQ056297@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
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");
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201904250828.x3P8SsJQ056297>