// SPDX-License-Identifier: GPL-2.0-only /* * Xen grant DMA-mapping layer - contains special DMA-mapping routines * for providing grant references as DMA addresses to be used by frontends * (e.g. virtio) in Xen guests * * Copyright (c) 2021, Juergen Gross <jgross@suse.com>
*/
xa_lock_irqsave(&xen_grant_dma_devices, flags);
ret = xa_err(__xa_store(&xen_grant_dma_devices, (unsignedlong)dev, data,
GFP_ATOMIC));
xa_unlock_irqrestore(&xen_grant_dma_devices, flags);
return ret;
}
/* * DMA ops for Xen frontends (e.g. virtio). * * Used to act as a kind of software IOMMU for Xen guests by using grants as * DMA addresses. * Such a DMA address is formed by using the grant reference as a frame * number and setting the highest address bit (this bit is for the backend * to be able to distinguish it from e.g. a mmio address).
*/ staticvoid *xen_grant_dma_alloc(struct device *dev, size_t size,
dma_addr_t *dma_handle, gfp_t gfp, unsignedlong attrs)
{ struct xen_grant_dma_data *data; unsignedint i, n_pages = XEN_PFN_UP(size); unsignedlong pfn;
grant_ref_t grant; void *ret;
data = find_xen_grant_dma_data(dev); if (!data) return NULL;
if (unlikely(data->broken)) return NULL;
ret = alloc_pages_exact(n_pages * XEN_PAGE_SIZE, gfp); if (!ret) return NULL;
data = find_xen_grant_dma_data(dev); if (!data) return;
if (unlikely(data->broken)) return;
grant = dma_to_grant(dma_handle);
for (i = 0; i < n_pages; i++) { if (unlikely(!gnttab_end_foreign_access_ref(grant + i))) {
dev_alert(dev, "Grant still in use by backend domain, disabled for further use\n");
data->broken = true; return;
}
}
if (WARN_ON(dir == DMA_NONE)) return DMA_MAPPING_ERROR;
data = find_xen_grant_dma_data(dev); if (!data) return DMA_MAPPING_ERROR;
if (unlikely(data->broken)) return DMA_MAPPING_ERROR;
if (gnttab_alloc_grant_reference_seq(n_pages, &grant)) return DMA_MAPPING_ERROR;
for (i = 0; i < n_pages; i++) {
gnttab_grant_foreign_access_ref(grant + i, data->backend_domid,
pfn_to_gfn(page_to_xen_pfn(page) + i + pfn_offset),
dir == DMA_TO_DEVICE);
}
data = find_xen_grant_dma_data(dev); if (!data) return;
if (unlikely(data->broken)) return;
grant = dma_to_grant(dma_handle);
for (i = 0; i < n_pages; i++) { if (unlikely(!gnttab_end_foreign_access_ref(grant + i))) {
dev_alert(dev, "Grant still in use by backend domain, disabled for further use\n");
data->broken = true; return;
}
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.