Lines Matching +full:gpa +full:- +full:0
1 /*-
2 * SPDX-License-Identifier: BSD-2-Clause
49 #define VTD_DRHD_INCLUDE_PCI_ALL(Flags) (((Flags) >> 0) & 0x1)
63 #define VTD_CAP_SAGAW(cap) (((cap) >> 8) & 0x1F)
64 #define VTD_CAP_ND(cap) ((cap) & 0x7)
65 #define VTD_CAP_CM(cap) (((cap) >> 7) & 0x1)
66 #define VTD_CAP_SPS(cap) (((cap) >> 34) & 0xF)
67 #define VTD_CAP_RWBF(cap) (((cap) >> 4) & 0x1)
69 #define VTD_ECAP_DI(ecap) (((ecap) >> 2) & 0x1)
70 #define VTD_ECAP_COHERENCY(ecap) ((ecap) & 0x1)
71 #define VTD_ECAP_IRO(ecap) (((ecap) >> 8) & 0x3FF)
92 #define VTD_ROOT_PRESENT 0x1
93 #define VTD_CTX_PRESENT 0x1
96 #define VTD_PTE_RD (1UL << 0)
99 #define VTD_PTE_ADDR_M (0x000FFFFFFFFFF000UL)
101 #define VTD_RID2IDX(rid) (((rid) & 0xff) * 2)
132 nd = VTD_CAP_ND(vtdmap->cap); in vtd_max_domains()
135 case 0: in vtd_max_domains()
150 panic("vtd_max_domains: invalid value of nd (0x%0x)", nd); in vtd_max_domains()
160 /* Skip domain id 0 - it is reserved when Caching Mode field is set */ in domain_id()
163 if (dom->id == id) in domain_id()
186 for (i = 0; i < drhd_num; i++) { in vtd_device_scope()
189 if (VTD_DRHD_INCLUDE_PCI_ALL(drhd->Flags)) { in vtd_device_scope()
191 * From Intel VT-d arch spec, version 3.0: in vtd_device_scope()
200 end = (char *)drhd + drhd->Header.Length; in vtd_device_scope()
201 remaining = drhd->Header.Length - sizeof(ACPI_DMAR_HARDWARE_UNIT); in vtd_device_scope()
203 device_scope = (ACPI_DMAR_DEVICE_SCOPE *)(end - remaining); in vtd_device_scope()
204 remaining -= device_scope->Length; in vtd_device_scope()
206 switch (device_scope->EntryType){ in vtd_device_scope()
207 /* 0x01 and 0x02 are PCI device entries */ in vtd_device_scope()
208 case 0x01: in vtd_device_scope()
209 case 0x02: in vtd_device_scope()
215 if (PCI_RID2BUS(rid) != device_scope->Bus) in vtd_device_scope()
218 pathend = (char *)device_scope + device_scope->Length; in vtd_device_scope()
219 pathremaining = device_scope->Length - sizeof(ACPI_DMAR_DEVICE_SCOPE); in vtd_device_scope()
221 path = (ACPI_DMAR_PCI_PATH *)(pathend - pathremaining); in vtd_device_scope()
222 pathremaining -= sizeof(ACPI_DMAR_PCI_PATH); in vtd_device_scope()
224 if (PCI_RID2SLOT(rid) != path->Device) in vtd_device_scope()
226 if (PCI_RID2FUNC(rid) != path->Function) in vtd_device_scope()
243 if (VTD_ECAP_COHERENCY(vtdmap->ext_cap) == 0) in vtd_wbflush()
246 if (VTD_CAP_RWBF(vtdmap->cap)) { in vtd_wbflush()
247 vtdmap->gcr = VTD_GCR_WBF; in vtd_wbflush()
248 while ((vtdmap->gsr & VTD_GSR_WBFS) != 0) in vtd_wbflush()
257 vtdmap->ccr = VTD_CCR_ICC | VTD_CCR_CIRG_GLOBAL; in vtd_ctx_global_invalidate()
258 while ((vtdmap->ccr & VTD_CCR_ICC) != 0) in vtd_ctx_global_invalidate()
270 offset = VTD_ECAP_IRO(vtdmap->ext_cap) * 16; in vtd_iotlb_global_invalidate()
278 if ((val & VTD_IIR_IVT) == 0) in vtd_iotlb_global_invalidate()
287 vtdmap->gcr = VTD_GCR_TE; in vtd_translation_enable()
288 while ((vtdmap->gsr & VTD_GSR_TES) == 0) in vtd_translation_enable()
296 vtdmap->gcr = 0; in vtd_translation_disable()
297 while ((vtdmap->gsr & VTD_GSR_TES) != 0) in vtd_translation_disable()
319 * physical addresses 0xfed90000 and 0xfeda0000 respectively. in vtd_init()
320 * set vtd.regmap.0.addr=0xfed90000 in vtd_init()
321 * set vtd.regmap.1.addr=0xfeda0000 in vtd_init()
323 for (units = 0; units < DRHD_MAX_UNITS; units++) { in vtd_init()
325 if (getenv_ulong(envname, &mapaddr) == 0) in vtd_init()
330 if (units > 0) in vtd_init()
334 status = AcpiGetTable(ACPI_SIG_DMAR, 0, (ACPI_TABLE_HEADER **)&dmar); in vtd_init()
338 end = (char *)dmar + dmar->Header.Length; in vtd_init()
339 remaining = dmar->Header.Length - sizeof(ACPI_TABLE_DMAR); in vtd_init()
341 hdr = (ACPI_DMAR_HEADER *)(end - remaining); in vtd_init()
342 if (hdr->Length > remaining) in vtd_init()
345 * From Intel VT-d arch spec, version 1.3: in vtd_init()
348 * type 0 (DRHD) enumerated before remapping structures of in vtd_init()
351 if (hdr->Type != ACPI_DMAR_TYPE_HARDWARE_UNIT) in vtd_init()
356 vtdmaps[units] = (struct vtdmap *)PHYS_TO_DMAP(drhd->Address); in vtd_init()
359 remaining -= hdr->Length; in vtd_init()
362 if (units <= 0) in vtd_init()
369 for (i = 0; i < drhd_num; i++){ in vtd_init()
372 if (VTD_CAP_CM(vtdmap->cap) != 0) in vtd_init()
381 * Set up the root-table to point to the context-entry tables in vtd_init()
383 for (i = 0; i < 256; i++) { in vtd_init()
386 panic("ctx table (0x%0lx) not page aligned", ctx_paddr); in vtd_init()
391 return (0); in vtd_init()
405 for (i = 0; i < drhd_num; i++) { in vtd_enable()
410 vtdmap->rta = vtophys(root_table); in vtd_enable()
411 vtdmap->gcr = VTD_GCR_SRTP; in vtd_enable()
412 while ((vtdmap->gsr & VTD_GSR_RTPS) == 0) in vtd_enable()
428 for (i = 0; i < drhd_num; i++) { in vtd_disable()
448 pt_paddr = vtophys(dom->ptp); in vtd_add_device()
465 ctxp[idx + 1] = dom->addrwidth | (dom->id << 8); in vtd_add_device()
467 if (VTD_ECAP_DI(vtdmap->ext_cap)) in vtd_add_device()
470 ctxp[idx] = 0; in vtd_add_device()
478 return (0); in vtd_add_device()
496 ctxp[idx] = 0; in vtd_remove_device()
497 ctxp[idx + 1] = 0; in vtd_remove_device()
502 * XXX use device-selective invalidation for Context Cache in vtd_remove_device()
503 * XXX use domain-selective invalidation for IOTLB in vtd_remove_device()
505 for (i = 0; i < drhd_num; i++) { in vtd_remove_device()
510 return (0); in vtd_remove_device()
513 #define CREATE_MAPPING 0
517 vtd_update_mapping(void *arg, vm_paddr_t gpa, vm_paddr_t hpa, uint64_t len, in vtd_update_mapping() argument
525 ptpindex = 0; in vtd_update_mapping()
526 ptpshift = 0; in vtd_update_mapping()
528 KASSERT(gpa + len > gpa, ("%s: invalid gpa range %#lx/%#lx", __func__, in vtd_update_mapping()
529 gpa, len)); in vtd_update_mapping()
530 KASSERT(gpa + len <= dom->maxaddr, ("%s: gpa range %#lx/%#lx beyond " in vtd_update_mapping()
531 "domain maxaddr %#lx", __func__, gpa, len, dom->maxaddr)); in vtd_update_mapping()
533 if (gpa & PAGE_MASK) in vtd_update_mapping()
534 panic("vtd_create_mapping: unaligned gpa 0x%0lx", gpa); in vtd_update_mapping()
537 panic("vtd_create_mapping: unaligned hpa 0x%0lx", hpa); in vtd_update_mapping()
540 panic("vtd_create_mapping: unaligned len 0x%0lx", len); in vtd_update_mapping()
546 * - supported super page size in vtd_update_mapping()
547 * - alignment of the region starting at 'gpa' and 'hpa' in vtd_update_mapping()
548 * - length of the region 'len' in vtd_update_mapping()
551 for (i = 3; i >= 0; i--) { in vtd_update_mapping()
553 if ((dom->spsmask & (1 << i)) != 0 && in vtd_update_mapping()
554 (gpa & (spsize - 1)) == 0 && in vtd_update_mapping()
555 (hpa & (spsize - 1)) == 0 && in vtd_update_mapping()
559 spshift -= 9; in vtd_update_mapping()
562 ptp = dom->ptp; in vtd_update_mapping()
563 nlevels = dom->pt_levels; in vtd_update_mapping()
564 while (--nlevels >= 0) { in vtd_update_mapping()
566 ptpindex = (gpa >> ptpshift) & 0x1FF; in vtd_update_mapping()
574 * We are working on a non-leaf page table page. in vtd_update_mapping()
579 if (ptp[ptpindex] == 0) { in vtd_update_mapping()
587 if ((gpa & ((1UL << ptpshift) - 1)) != 0) in vtd_update_mapping()
588 panic("gpa 0x%lx and ptpshift %d mismatch", gpa, ptpshift); in vtd_update_mapping()
591 * Update the 'gpa' -> 'hpa' mapping in vtd_update_mapping()
594 ptp[ptpindex] = 0; in vtd_update_mapping()
598 if (nlevels > 0) in vtd_update_mapping()
606 vtd_create_mapping(void *arg, vm_paddr_t gpa, vm_paddr_t hpa, uint64_t len, in vtd_create_mapping() argument
610 *res_len = vtd_update_mapping(arg, gpa, hpa, len, CREATE_MAPPING); in vtd_create_mapping()
611 return (0); in vtd_create_mapping()
615 vtd_remove_mapping(void *arg, vm_paddr_t gpa, uint64_t len, uint64_t *res_len) in vtd_remove_mapping() argument
618 *res_len = vtd_update_mapping(arg, gpa, 0, len, REMOVE_MAPPING); in vtd_remove_mapping()
619 return (0); in vtd_remove_mapping()
630 * XXX use domain-selective invalidation for IOTLB in vtd_invalidate_tlb()
632 for (i = 0; i < drhd_num; i++) { in vtd_invalidate_tlb()
636 return (0); in vtd_invalidate_tlb()
647 if (drhd_num <= 0) in vtd_create_domain()
654 addr = 0; in vtd_create_domain()
655 for (gaw = 0; addr < maxaddr; gaw++) in vtd_create_domain()
658 res = (gaw - 12) % 9; in vtd_create_domain()
659 if (res == 0) in vtd_create_domain()
662 agaw = gaw + 9 - res; in vtd_create_domain()
673 addrwidth = 0; in vtd_create_domain()
675 tmp = ~0; in vtd_create_domain()
676 for (i = 0; i < drhd_num; i++) { in vtd_create_domain()
679 tmp &= VTD_CAP_SAGAW(vtdmap->cap); in vtd_create_domain()
682 for (i = 0; i < 5; i++) { in vtd_create_domain()
683 if ((tmp & (1 << i)) != 0 && sagaw >= agaw) in vtd_create_domain()
693 panic("vtd_create_domain: SAGAW 0x%x does not support AGAW %d", in vtd_create_domain()
698 dom->pt_levels = pt_levels; in vtd_create_domain()
699 dom->addrwidth = addrwidth; in vtd_create_domain()
700 dom->id = domain_id(); in vtd_create_domain()
701 dom->maxaddr = maxaddr; in vtd_create_domain()
702 dom->ptp = malloc(PAGE_SIZE, M_VTD, M_ZERO | M_WAITOK); in vtd_create_domain()
703 if ((uintptr_t)dom->ptp & PAGE_MASK) in vtd_create_domain()
704 panic("vtd_create_domain: ptp (%p) not page aligned", dom->ptp); in vtd_create_domain()
721 dom->spsmask = ~0; in vtd_create_domain()
722 for (i = 0; i < drhd_num; i++) { in vtd_create_domain()
725 dom->spsmask &= VTD_CAP_SPS(vtdmap->cap); in vtd_create_domain()
741 for (i = 0; i < 512; i++) { in vtd_free_ptp()
742 if ((ptp[i] & (VTD_PTE_RD | VTD_PTE_WR)) == 0) in vtd_free_ptp()
744 if ((ptp[i] & VTD_PTE_SUPERPAGE) != 0) in vtd_free_ptp()
747 vtd_free_ptp(nlp, level - 1); in vtd_free_ptp()
763 vtd_free_ptp(dom->ptp, dom->pt_levels); in vtd_destroy_domain()