Lines Matching +full:iommu +full:- +full:ctx
1 /*-
2 * SPDX-License-Identifier: BSD-2-Clause
4 * Copyright (c) 2013-2015 The FreeBSD Foundation
71 #include <dev/iommu/busdma_iommu.h>
72 #include <x86/iommu/intel_reg.h>
73 #include <x86/iommu/x86_iommu.h>
74 #include <x86/iommu/intel_dmar.h>
104 ptrend = (char *)dmartbl + dmartbl->Header.Length; in dmar_iterate_tbl()
109 if (dmarh->Length <= 0) { in dmar_iterate_tbl()
111 dmarh->Length); in dmar_iterate_tbl()
114 ptr += dmarh->Length; in dmar_iterate_tbl()
131 if (dmarh->Type != ACPI_DMAR_TYPE_HARDWARE_UNIT) in dmar_find_iter()
135 if (fia->i == 0) { in dmar_find_iter()
136 fia->res = (ACPI_DMAR_HARDWARE_UNIT *)dmarh; in dmar_find_iter()
139 fia->i--; in dmar_find_iter()
158 if (dmarh->Type == ACPI_DMAR_TYPE_HARDWARE_UNIT) in dmar_count_iter()
175 if (dmarh->Type == ACPI_DMAR_TYPE_HARDWARE_AFFINITY) { in dmar_rhsa_iter()
178 if (adr->BaseAddress == ria->base) in dmar_rhsa_iter()
179 ria->proxim_dom = adr->ProximityDomain; in dmar_rhsa_iter()
206 haw = dmartbl->Width + 1; in dmar_identify()
212 printf("DMAR HAW=%d flags=<%b>\n", dmartbl->Width, in dmar_identify()
213 (unsigned)dmartbl->Flags, in dmar_identify()
235 DMAR_REG_RID, dmarh->Address, PAGE_SIZE); in dmar_identify()
239 i, (uintmax_t)dmarh->Address, error); in dmar_identify()
245 ria.base = dmarh->Address; in dmar_identify()
246 ria.proxim_dom = -1; in dmar_identify()
248 acpi_set_domain(dmar_devs[i], ria.proxim_dom == -1 ? in dmar_identify()
269 iommu_fini_busdma(&unit->iommu); in dmar_release_resources()
275 if (unit->regs != NULL) { in dmar_release_resources()
276 bus_deactivate_resource(dev, SYS_RES_MEMORY, unit->reg_rid, in dmar_release_resources()
277 unit->regs); in dmar_release_resources()
278 bus_release_resource(dev, SYS_RES_MEMORY, unit->reg_rid, in dmar_release_resources()
279 unit->regs); in dmar_release_resources()
280 unit->regs = NULL; in dmar_release_resources()
282 if (unit->domids != NULL) { in dmar_release_resources()
283 delete_unrhdr(unit->domids); in dmar_release_resources()
284 unit->domids = NULL; in dmar_release_resources()
286 if (unit->ctx_obj != NULL) { in dmar_release_resources()
287 vm_object_deallocate(unit->ctx_obj); in dmar_release_resources()
288 unit->ctx_obj = NULL; in dmar_release_resources()
290 sysctl_ctx_free(&unit->iommu.sysctl_ctx); in dmar_release_resources()
305 dmd = &unit->x86c.intrs[i]; in dmar_remap_intr()
306 if (irq == dmd->irq) { in dmar_remap_intr()
313 dmd->msi_data = msi_data; in dmar_remap_intr()
314 dmd->msi_addr = msi_addr; in dmar_remap_intr()
315 (dmd->disable_intr)(DMAR2IOMMU(unit)); in dmar_remap_intr()
316 dmar_write4(unit, dmd->msi_data_reg, dmd->msi_data); in dmar_remap_intr()
317 dmar_write4(unit, dmd->msi_addr_reg, dmd->msi_addr); in dmar_remap_intr()
318 dmar_write4(unit, dmd->msi_uaddr_reg, in dmar_remap_intr()
319 dmd->msi_addr >> 32); in dmar_remap_intr()
320 (dmd->enable_intr)(DMAR2IOMMU(unit)); in dmar_remap_intr()
336 (uintmax_t)dmaru->Address, DMAR_MAJOR_VER(unit->hw_ver), in dmar_print_caps()
337 DMAR_MINOR_VER(unit->hw_ver), dmaru->Segment, in dmar_print_caps()
338 dmaru->Flags, "\020\001INCLUDE_ALL_PCI"); in dmar_print_caps()
339 caphi = unit->hw_cap >> 32; in dmar_print_caps()
340 device_printf(dev, "cap=%b,", (u_int)unit->hw_cap, in dmar_print_caps()
344 DMAR_CAP_ND(unit->hw_cap), DMAR_CAP_SAGAW(unit->hw_cap), in dmar_print_caps()
345 DMAR_CAP_MGAW(unit->hw_cap), DMAR_CAP_FRO(unit->hw_cap), in dmar_print_caps()
346 DMAR_CAP_NFR(unit->hw_cap), DMAR_CAP_SPS(unit->hw_cap)); in dmar_print_caps()
347 if ((unit->hw_cap & DMAR_CAP_PSI) != 0) in dmar_print_caps()
348 printf(", mamv=%d", DMAR_CAP_MAMV(unit->hw_cap)); in dmar_print_caps()
350 ecaphi = unit->hw_ecap >> 32; in dmar_print_caps()
351 device_printf(dev, "ecap=%b,", (u_int)unit->hw_ecap, in dmar_print_caps()
355 printf("mhmw=%d, iro=%d\n", DMAR_ECAP_MHMV(unit->hw_ecap), in dmar_print_caps()
356 DMAR_ECAP_IRO(unit->hw_ecap)); in dmar_print_caps()
370 unit->iommu.unit = device_get_unit(dev); in dmar_attach()
371 unit->iommu.dev = dev; in dmar_attach()
372 sysctl_ctx_init(&unit->iommu.sysctl_ctx); in dmar_attach()
373 dmaru = dmar_find_by_index(unit->iommu.unit); in dmar_attach()
376 unit->segment = dmaru->Segment; in dmar_attach()
377 unit->base = dmaru->Address; in dmar_attach()
378 unit->reg_rid = DMAR_REG_RID; in dmar_attach()
379 unit->regs = bus_alloc_resource_any(dev, SYS_RES_MEMORY, in dmar_attach()
380 &unit->reg_rid, RF_ACTIVE); in dmar_attach()
381 if (unit->regs == NULL) { in dmar_attach()
383 dmar_devs[unit->iommu.unit] = NULL; in dmar_attach()
386 unit->hw_ver = dmar_read4(unit, DMAR_VER_REG); in dmar_attach()
387 unit->hw_cap = dmar_read8(unit, DMAR_CAP_REG); in dmar_attach()
388 unit->hw_ecap = dmar_read8(unit, DMAR_ECAP_REG); in dmar_attach()
392 unit->memdomain = acpi_get_domain(dev); in dmar_attach()
394 TUNABLE_UINT64_FETCH("hw.iommu.dmar.timeout", &timeout); in dmar_attach()
398 unit->x86c.intrs[i].irq = -1; in dmar_attach()
400 dmd = &unit->x86c.intrs[DMAR_INTR_FAULT]; in dmar_attach()
401 dmd->name = "fault"; in dmar_attach()
402 dmd->irq_rid = DMAR_FAULT_IRQ_RID; in dmar_attach()
403 dmd->handler = dmar_fault_intr; in dmar_attach()
404 dmd->msi_data_reg = DMAR_FEDATA_REG; in dmar_attach()
405 dmd->msi_addr_reg = DMAR_FEADDR_REG; in dmar_attach()
406 dmd->msi_uaddr_reg = DMAR_FEUADDR_REG; in dmar_attach()
407 dmd->enable_intr = dmar_enable_fault_intr; in dmar_attach()
408 dmd->disable_intr = dmar_disable_fault_intr; in dmar_attach()
412 dmar_devs[unit->iommu.unit] = NULL; in dmar_attach()
415 dmar_write4(unit, dmd->msi_data_reg, dmd->msi_data); in dmar_attach()
416 dmar_write4(unit, dmd->msi_addr_reg, dmd->msi_addr); in dmar_attach()
417 dmar_write4(unit, dmd->msi_uaddr_reg, dmd->msi_addr >> 32); in dmar_attach()
420 dmd = &unit->x86c.intrs[DMAR_INTR_QI]; in dmar_attach()
421 dmd->name = "qi"; in dmar_attach()
422 dmd->irq_rid = DMAR_QI_IRQ_RID; in dmar_attach()
423 dmd->handler = dmar_qi_intr; in dmar_attach()
424 dmd->msi_data_reg = DMAR_IEDATA_REG; in dmar_attach()
425 dmd->msi_addr_reg = DMAR_IEADDR_REG; in dmar_attach()
426 dmd->msi_uaddr_reg = DMAR_IEUADDR_REG; in dmar_attach()
427 dmd->enable_intr = dmar_enable_qi_intr; in dmar_attach()
428 dmd->disable_intr = dmar_disable_qi_intr; in dmar_attach()
432 dmar_devs[unit->iommu.unit] = NULL; in dmar_attach()
436 dmar_write4(unit, dmd->msi_data_reg, dmd->msi_data); in dmar_attach()
437 dmar_write4(unit, dmd->msi_addr_reg, dmd->msi_addr); in dmar_attach()
438 dmar_write4(unit, dmd->msi_uaddr_reg, dmd->msi_addr >> 32); in dmar_attach()
441 mtx_init(&unit->iommu.lock, "dmarhw", NULL, MTX_DEF); in dmar_attach()
442 unit->domids = new_unrhdr(0, dmar_nd2mask(DMAR_CAP_ND(unit->hw_cap)), in dmar_attach()
443 &unit->iommu.lock); in dmar_attach()
444 LIST_INIT(&unit->domains); in dmar_attach()
449 * domain-id value of zero is architecturally reserved. in dmar_attach()
450 * Software must not use domain-id value of zero in dmar_attach()
453 if ((unit->hw_cap & DMAR_CAP_CM) != 0) in dmar_attach()
454 alloc_unr_specific(unit->domids, 0); in dmar_attach()
456 unit->ctx_obj = vm_pager_allocate(OBJT_PHYS, NULL, IDX_TO_OFF(1 + in dmar_attach()
458 if (unit->memdomain != -1) { in dmar_attach()
459 unit->ctx_obj->domain.dr_policy = DOMAINSET_PREF( in dmar_attach()
460 unit->memdomain); in dmar_attach()
468 iommu_pgalloc(unit->ctx_obj, 0, IOMMU_PGF_WAITOK | IOMMU_PGF_ZERO); in dmar_attach()
474 dmar_devs[unit->iommu.unit] = NULL; in dmar_attach()
481 dmar_devs[unit->iommu.unit] = NULL; in dmar_attach()
484 if ((unit->hw_ecap & DMAR_ECAP_DI) != 0) { in dmar_attach()
489 dmar_devs[unit->iommu.unit] = NULL; in dmar_attach()
498 dmar_devs[unit->iommu.unit] = NULL; in dmar_attach()
504 dmar_devs[unit->iommu.unit] = NULL; in dmar_attach()
510 dmar_devs[unit->iommu.unit] = NULL; in dmar_attach()
523 error = iommu_init_busdma(&unit->iommu); in dmar_attach()
526 dmar_devs[unit->iommu.unit] = NULL; in dmar_attach()
536 dmar_devs[unit->iommu.unit] = NULL; in dmar_attach()
630 for (depth--; depth != -1; depth--) { in dmar_dev_path()
675 if (devscope->Length < sizeof(*devscope)) { in dmar_match_devscope()
677 devscope->Length); in dmar_match_devscope()
678 return (-1); in dmar_match_devscope()
680 if (devscope->EntryType != ACPI_DMAR_SCOPE_TYPE_ENDPOINT && in dmar_match_devscope()
681 devscope->EntryType != ACPI_DMAR_SCOPE_TYPE_BRIDGE) in dmar_match_devscope()
683 path_len = devscope->Length - sizeof(*devscope); in dmar_match_devscope()
686 devscope->Length); in dmar_match_devscope()
687 return (-1); in dmar_match_devscope()
693 devscope->Length); in dmar_match_devscope()
694 return (-1); in dmar_match_devscope()
697 return (dmar_match_pathes(devscope->Bus, path, path_len, dev_busno, in dmar_match_devscope()
698 dev_path, dev_path_len, devscope->EntryType)); in dmar_match_devscope()
710 dmarh = dmar_find_by_index(unit->iommu.unit); in dmar_match_by_path()
713 if (dmarh->Segment != dev_domain) in dmar_match_by_path()
715 if ((dmarh->Flags & ACPI_DMAR_INCLUDE_ALL) != 0) { in dmar_match_by_path()
721 ptrend = (char *)dmarh + dmarh->Header.Length; in dmar_match_by_path()
724 ptr += devscope->Length; in dmar_match_by_path()
727 if (match == -1) in dmar_match_by_path()
790 pci_get_function(dev), unit->iommu.unit, banner); in dmar_find()
795 iommu_device_set_iommu_prop(dev, unit->iommu.dev); in dmar_find()
822 ptrend = (char *)dmarh + dmarh->Header.Length; in dmar_find_nonpci()
827 ptr += devscope->Length; in dmar_find_nonpci()
828 if (devscope->EntryType != entry_type) in dmar_find_nonpci()
830 if (devscope->EnumerationId != id) in dmar_find_nonpci()
843 if (devscope->Length - sizeof(ACPI_DMAR_DEVICE_SCOPE) in dmar_find_nonpci()
848 *rid = PCI_RID(devscope->Bus, in dmar_find_nonpci()
849 path->Device, path->Function); in dmar_find_nonpci()
870 iommu_device_set_iommu_prop(dev, unit->iommu.dev); in dmar_find_hpet()
884 iommu_device_set_iommu_prop(apic_dev, unit->iommu.dev); in dmar_find_ioapic()
911 if (dmarh->Type != ACPI_DMAR_TYPE_RESERVED_MEMORY) in dmar_rmrr_iter()
916 if (resmem->Segment != ria->dev_domain) in dmar_rmrr_iter()
920 ptrend = (char *)resmem + resmem->Header.Length; in dmar_rmrr_iter()
925 ptr += devscope->Length; in dmar_rmrr_iter()
926 match = dmar_match_devscope(devscope, ria->dev_busno, in dmar_rmrr_iter()
927 ria->dev_path, ria->dev_path_len); in dmar_rmrr_iter()
929 entry = iommu_gas_alloc_entry(DOM2IODOM(ria->domain), in dmar_rmrr_iter()
931 entry->start = resmem->BaseAddress; in dmar_rmrr_iter()
933 entry->end = resmem->EndAddress; in dmar_rmrr_iter()
934 TAILQ_INSERT_TAIL(ria->rmrr_entries, entry, in dmar_rmrr_iter()
971 dev = pci_find_dbsf(segment, busno, path->Device, in dmar_path_dev()
972 path->Function); in dmar_path_dev()
973 if (i != path_len - 1) { in dmar_path_dev()
974 busno = pci_cfgregread(segment, busno, path->Device, in dmar_path_dev()
975 path->Function, PCIR_SECBUS_1, 1); in dmar_path_dev()
979 *rid = PCI_RID(busno, path->Device, path->Function); in dmar_path_dev()
1000 if (dmarh->Type != ACPI_DMAR_TYPE_RESERVED_MEMORY) in dmar_inst_rmrr_iter()
1004 if (resmem->Segment != iria->dmar->segment) in dmar_inst_rmrr_iter()
1008 ptrend = (const char *)resmem + resmem->Header.Length; in dmar_inst_rmrr_iter()
1013 ptr += devscope->Length; in dmar_inst_rmrr_iter()
1015 if (devscope->EntryType != ACPI_DMAR_SCOPE_TYPE_ENDPOINT) in dmar_inst_rmrr_iter()
1018 dev_path_len = (devscope->Length - in dmar_inst_rmrr_iter()
1020 dev = dmar_path_dev(resmem->Segment, dev_path_len, in dmar_inst_rmrr_iter()
1021 devscope->Bus, in dmar_inst_rmrr_iter()
1027 iria->dmar->iommu.unit, in dmar_inst_rmrr_iter()
1028 (uintmax_t)resmem->BaseAddress, in dmar_inst_rmrr_iter()
1029 (uintmax_t)resmem->EndAddress, in dmar_inst_rmrr_iter()
1031 dmar_print_path(devscope->Bus, dev_path_len, in dmar_inst_rmrr_iter()
1035 unit = dmar_find_by_scope(resmem->Segment, in dmar_inst_rmrr_iter()
1036 devscope->Bus, in dmar_inst_rmrr_iter()
1039 if (iria->dmar != unit) in dmar_inst_rmrr_iter()
1041 dmar_get_ctx_for_devpath(iria->dmar, rid, in dmar_inst_rmrr_iter()
1042 resmem->Segment, devscope->Bus, in dmar_inst_rmrr_iter()
1047 if (iria->dmar != unit) in dmar_inst_rmrr_iter()
1049 iommu_instantiate_ctx(&(iria)->dmar->iommu, in dmar_inst_rmrr_iter()
1059 * Pre-create all contexts for the DMAR which have RMRR entries.
1077 if (!LIST_EMPTY(&dmar->domains)) { in dmar_instantiate_rmrr_ctxs()
1078 KASSERT((dmar->hw_gcmd & DMAR_GCMD_TE) == 0, in dmar_instantiate_rmrr_ctxs()
1080 dmar->iommu.unit)); in dmar_instantiate_rmrr_ctxs()
1084 dmar->iommu.unit); in dmar_instantiate_rmrr_ctxs()
1089 dmar->iommu.unit); in dmar_instantiate_rmrr_ctxs()
1092 "error %d\n", dmar->iommu.unit, error); in dmar_instantiate_rmrr_ctxs()
1114 domain, domain->domain, domain->mgaw, domain->agaw, domain->pglvl, in dmar_print_domain()
1115 (uintmax_t)domain->iodom.end, domain->refs, domain->ctx_cnt, in dmar_print_domain()
1116 domain->iodom.flags, domain->pgtbl_obj, domain->iodom.entries_cnt); in dmar_print_domain()
1128 struct iommu_ctx *ctx; in DB_SHOW_COMMAND_FLAGS() local
1175 LIST_FOREACH(domain, &unit->domains, link) { in DB_SHOW_COMMAND_FLAGS()
1176 LIST_FOREACH(ctx, &domain->iodom.contexts, link) { in DB_SHOW_COMMAND_FLAGS()
1177 if (pci_domain == unit->segment && in DB_SHOW_COMMAND_FLAGS()
1178 bus == pci_get_bus(ctx->tag->owner) && in DB_SHOW_COMMAND_FLAGS()
1179 device == pci_get_slot(ctx->tag->owner) && in DB_SHOW_COMMAND_FLAGS()
1180 function == pci_get_function(ctx->tag-> in DB_SHOW_COMMAND_FLAGS()
1200 db_printf("dmar%d at %p, root at 0x%jx, ver 0x%x\n", unit->iommu.unit, in dmar_print_one()
1209 if (unit->ir_enabled) { in dmar_print_one()
1211 unit->irt, (uintmax_t)unit->irt_phys, unit->irte_cnt); in dmar_print_one()
1218 for (i = 0; i < DMAR_CAP_NFR(unit->hw_cap); i++) { in dmar_print_one()
1219 frir = (DMAR_CAP_FRO(unit->hw_cap) + i) * 16; in dmar_print_one()
1229 if (unit->qi_enabled) { in dmar_print_one()
1234 (uintmax_t)unit->x86c.inv_queue, in dmar_print_one()
1236 (uintmax_t)unit->x86c.inv_queue_size, in dmar_print_one()
1239 unit->x86c.inv_queue_avail, in dmar_print_one()
1242 (uintmax_t)unit->x86c.inv_waitd_seq_hw, in dmar_print_one()
1243 &unit->x86c.inv_waitd_seq_hw, in dmar_print_one()
1244 (uintmax_t)unit->x86c.inv_waitd_seq_hw_phys, in dmar_print_one()
1245 unit->x86c.inv_waitd_seq, in dmar_print_one()
1246 unit->x86c.inv_waitd_gen); in dmar_print_one()
1253 LIST_FOREACH(domain, &unit->domains, link) { in dmar_print_one()
1296 return (&dmar->iommu); in dmar_find_method()
1305 return (&dmar->x86c); in dmar_get_x86_common()