Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F160230095
D27503.id80429.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
5 KB
Referenced Files
None
Subscribers
None
D27503.id80429.diff
View Options
Index: sys/dev/iommu/iommu.h
===================================================================
--- sys/dev/iommu/iommu.h
+++ sys/dev/iommu/iommu.h
@@ -199,6 +199,8 @@
struct iommu_map_entry *entry, u_int eflags, u_int flags, vm_page_t *ma);
int iommu_gas_reserve_region(struct iommu_domain *domain, iommu_gaddr_t start,
iommu_gaddr_t end, struct iommu_map_entry **entry0);
+int iommu_gas_reserve_region_extend(struct iommu_domain *domain,
+ iommu_gaddr_t start, iommu_gaddr_t end);
void iommu_set_buswide_ctx(struct iommu_unit *unit, u_int busno);
bool iommu_is_buswide_ctx(struct iommu_unit *unit, u_int busno);
Index: sys/dev/iommu/iommu_gas.c
===================================================================
--- sys/dev/iommu/iommu_gas.c
+++ sys/dev/iommu/iommu_gas.c
@@ -677,6 +677,22 @@
return (0);
}
+static int
+iommu_gas_reserve_region_locked(struct iommu_domain *domain,
+ iommu_gaddr_t start, iommu_gaddr_t end, struct iommu_map_entry *entry)
+{
+ int error;
+
+ IOMMU_DOMAIN_ASSERT_LOCKED(domain);
+
+ entry->start = start;
+ entry->end = end;
+ error = iommu_gas_alloc_region(domain, entry, IOMMU_MF_CANWAIT);
+ if (error == 0)
+ entry->flags |= IOMMU_MAP_ENTRY_UNMAPPED;
+ return (error);
+}
+
int
iommu_gas_reserve_region(struct iommu_domain *domain, iommu_gaddr_t start,
iommu_gaddr_t end, struct iommu_map_entry **entry0)
@@ -685,12 +701,8 @@
int error;
entry = iommu_gas_alloc_entry(domain, IOMMU_PGF_WAITOK);
- entry->start = start;
- entry->end = end;
IOMMU_DOMAIN_LOCK(domain);
- error = iommu_gas_alloc_region(domain, entry, IOMMU_MF_CANWAIT);
- if (error == 0)
- entry->flags |= IOMMU_MAP_ENTRY_UNMAPPED;
+ error = iommu_gas_reserve_region_locked(domain, start, end, entry);
IOMMU_DOMAIN_UNLOCK(domain);
if (error != 0)
iommu_gas_free_entry(domain, entry);
@@ -699,6 +711,56 @@
return (error);
}
+/*
+ * As in iommu_gas_reserve_region, reserve [start, end), but allow for existing
+ * entries.
+ */
+int
+iommu_gas_reserve_region_extend(struct iommu_domain *domain,
+ iommu_gaddr_t start, iommu_gaddr_t end)
+{
+ struct iommu_map_entry *entry, *next, *prev, key = {};
+ iommu_gaddr_t entry_start, entry_end;
+ int error;
+
+ error = 0;
+ entry = NULL;
+ end = ummin(end, domain->end);
+ while (start < end) {
+ /* Preallocate an entry. */
+ if (entry == NULL)
+ entry = iommu_gas_alloc_entry(domain,
+ IOMMU_PGF_WAITOK);
+ /* Calculate the free region from here to the next entry. */
+ key.start = key.end = start;
+ IOMMU_DOMAIN_LOCK(domain);
+ next = RB_NFIND(iommu_gas_entries_tree, &domain->rb_root, &key);
+ KASSERT(next != NULL, ("domain %p with end %#jx has no entry "
+ "after %#jx", domain, (uintmax_t)domain->end,
+ (uintmax_t)start));
+ entry_end = ummin(end, next->start);
+ prev = RB_PREV(iommu_gas_entries_tree, &domain->rb_root, next);
+ if (prev != NULL)
+ entry_start = ummax(start, prev->end);
+ else
+ entry_start = start;
+ start = next->end;
+ /* Reserve the region if non-empty. */
+ if (entry_start != entry_end) {
+ error = iommu_gas_reserve_region_locked(domain,
+ entry_start, entry_end, entry);
+ if (error != 0)
+ break;
+ entry = NULL;
+ }
+ IOMMU_DOMAIN_UNLOCK(domain);
+ }
+ /* Release a preallocated entry if it was not used. */
+ if (entry != NULL)
+ iommu_gas_free_entry(domain, entry);
+ return (error);
+}
+
struct iommu_map_entry *
iommu_map_alloc_entry(struct iommu_domain *domain, u_int flags)
{
Index: sys/x86/iommu/intel_ctx.c
===================================================================
--- sys/x86/iommu/intel_ctx.c
+++ sys/x86/iommu/intel_ctx.c
@@ -317,6 +317,64 @@
return (error);
}
+/*
+ * Reserve in the guest address space any host memory addresses assigned
+ * to the same PCIe root port. PCI transactions routed with memory addresses
+ * may be routed without respect to translation, and so transactions for such
+ * aliased addresses may be misdirected.
+ */
+static int
+dmar_reserve_pci_regions(struct dmar_domain *domain, device_t dev)
+{
+ struct iommu_domain *iodom;
+ device_t root;
+ uint32_t val;
+ uint64_t base, limit;
+ int error;
+
+ iodom = DOM2IODOM(domain);
+
+ root = pci_find_pcie_root_port(dev);
+ if (root == NULL)
+ return (0);
+
+ /* Disable downstream memory */
+ base = PCI_PPBMEMBASE(0, pci_read_config(root, PCIR_MEMBASE_1, 2));
+ limit = PCI_PPBMEMLIMIT(0, pci_read_config(root, PCIR_MEMLIMIT_1, 2));
+ error = iommu_gas_reserve_region_extend(iodom, base, limit + 1);
+ if (bootverbose || error != 0)
+ device_printf(dev, "DMAR reserve [%#jx-%#jx] (error %d)\n",
+ base, limit + 1, error);
+ if (error != 0)
+ return (error);
+
+ /* Disable downstream prefetchable memory */
+ val = pci_read_config(root, PCIR_PMBASEL_1, 2);
+ if (val != 0 || pci_read_config(root, PCIR_PMLIMITL_1, 2) != 0) {
+ if ((val & PCIM_BRPM_MASK) == PCIM_BRPM_64) {
+ base = PCI_PPBMEMBASE(
+ pci_read_config(root, PCIR_PMBASEH_1, 4),
+ val);
+ limit = PCI_PPBMEMLIMIT(
+ pci_read_config(root, PCIR_PMLIMITH_1, 4),
+ pci_read_config(root, PCIR_PMLIMITL_1, 2));
+ } else {
+ base = PCI_PPBMEMBASE(0, val);
+ limit = PCI_PPBMEMLIMIT(0,
+ pci_read_config(root, PCIR_PMLIMITL_1, 2));
+ }
+ error = iommu_gas_reserve_region_extend(iodom, base,
+ limit + 1);
+ if (bootverbose || error != 0)
+ device_printf(dev, "DMAR reserve [%#jx-%#jx] "
+ "(error %d)\n", base, limit + 1, error);
+ if (error != 0)
+ return (error);
+ }
+
+ return (error);
+}
+
static struct dmar_domain *
dmar_domain_alloc(struct dmar_unit *dmar, bool id_mapped)
{
@@ -502,6 +560,8 @@
error = domain_init_rmrr(domain1, dev, bus,
slot, func, dev_domain, dev_busno, dev_path,
dev_path_len);
+ if (error == 0)
+ error = dmar_reserve_pci_regions(domain1, dev);
if (error != 0) {
dmar_domain_destroy(domain1);
TD_PINNED_ASSERT;
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Tue, Jun 23, 9:53 AM (17 h, 26 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
34239881
Default Alt Text
D27503.id80429.diff (5 KB)
Attached To
Mode
D27503: dmar: reserve memory windows of PCIe root port
Attached
Detach File
Event Timeline
Log In to Comment