diff options
author | Patrick Wildt <patrick@cvs.openbsd.org> | 2021-06-25 17:41:23 +0000 |
---|---|---|
committer | Patrick Wildt <patrick@cvs.openbsd.org> | 2021-06-25 17:41:23 +0000 |
commit | 65c96663997f4f903057aefb66e854f7a46b6fcc (patch) | |
tree | bbed60603e2682b465d2324de3865633019284a7 /sys/arch/arm64/dev/acpiiort.c | |
parent | 8ae46050b7612e67afb7a16fc8733a0f21804d2a (diff) |
While it seems like we can choose any I/O virtual address for peripheral
devices, this isn't really the case. It depends on the bus topology of
how devices are connected. In the case of PCIe, devices are assigned
addresses (in PCI BARs) from the PCI address spaces. Now if we take an
address from one of these address spaces for our IOVA, transfers from
from a PCI device to that address will terminate inside of the PCI bus.
This is because from the PCI buses' point-of-view, the address we chose
is part of its address space. To make sure we don't allocate addresses
from there, reserve the PCI addresses in the IOVA.
Note that smmu(4) currently gives each device its own IOVA. So the PCI
addresses will be reserved only in IOVA from PCI devices, and only the
addresses concerning the PCI bus it is connected to will be reserved.
All other devices behind an smmu(4) will not have any changes to their
IOVA.
ok kettenis@
Diffstat (limited to 'sys/arch/arm64/dev/acpiiort.c')
-rw-r--r-- | sys/arch/arm64/dev/acpiiort.c | 16 |
1 files changed, 15 insertions, 1 deletions
diff --git a/sys/arch/arm64/dev/acpiiort.c b/sys/arch/arm64/dev/acpiiort.c index 8569b4932d7..7bee4dac83e 100644 --- a/sys/arch/arm64/dev/acpiiort.c +++ b/sys/arch/arm64/dev/acpiiort.c @@ -1,4 +1,4 @@ -/* $OpenBSD: acpiiort.c,v 1.3 2021/03/15 22:56:48 patrick Exp $ */ +/* $OpenBSD: acpiiort.c,v 1.4 2021/06/25 17:41:22 patrick Exp $ */ /* * Copyright (c) 2021 Patrick Wildt <patrick@blueri.se> * @@ -103,6 +103,20 @@ acpiiort_smmu_map(struct acpi_iort_node *node, uint32_t rid, return dmat; } +void +acpiiort_smmu_reserve_region(struct acpi_iort_node *node, uint32_t rid, + bus_addr_t addr, bus_size_t size) +{ + struct acpiiort_smmu *as; + + SIMPLEQ_FOREACH(as, &acpiiort_smmu_list, as_list) { + if (as->as_node == node) { + as->as_reserve(as->as_cookie, rid, addr, size); + return; + } + } +} + bus_dma_tag_t acpiiort_device_map(struct aml_node *root, bus_dma_tag_t dmat) { |