Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

xen/grant-dma-ops: Retrieve the ID of backend's domain for DT devices

Use the presence of "iommus" property pointed to the IOMMU node with
recently introduced "xen,grant-dma" compatible as a clear indicator
of enabling Xen grant mappings scheme for that device and read the ID
of Xen domain where the corresponding backend is running. The domid
(domain ID) is used as an argument to the Xen grant mapping APIs.

To avoid the deferred probe timeout which takes place after reusing
generic IOMMU device tree bindings (because the IOMMU device never
becomes available) enable recently introduced stub IOMMU driver by
selecting XEN_GRANT_DMA_IOMMU.

Also introduce xen_is_grant_dma_device() to check whether xen-grant
DMA ops need to be set for a passed device.

Remove the hardcoded domid 0 in xen_grant_setup_dma_ops().

Signed-off-by: Oleksandr Tyshchenko <oleksandr_tyshchenko@epam.com>
Reviewed-by: Stefano Stabellini <sstabellini@kernel.org>
Link: https://lore.kernel.org/r/1654197833-25362-8-git-send-email-olekstysh@gmail.com
Signed-off-by: Juergen Gross <jgross@suse.com>

authored by

Oleksandr Tyshchenko and committed by
Juergen Gross
625ab90e 1ca55d50

+47 -7
+1
drivers/xen/Kconfig
··· 347 347 bool "Xen virtio support" 348 348 depends on VIRTIO 349 349 select XEN_GRANT_DMA_OPS 350 + select XEN_GRANT_DMA_IOMMU if OF 350 351 help 351 352 Enable virtio support for running as Xen guest. Depending on the 352 353 guest type this will require special support on the backend side
+41 -7
drivers/xen/grant-dma-ops.c
··· 56 56 * Such a DMA address is formed by using the grant reference as a frame 57 57 * number and setting the highest address bit (this bit is for the backend 58 58 * to be able to distinguish it from e.g. a mmio address). 59 - * 60 - * Note that for now we hard wire dom0 to be the backend domain. In order 61 - * to support any domain as backend we'd need to add a way to communicate 62 - * the domid of this backend, e.g. via Xenstore, via the PCI-device's 63 - * config space or DT/ACPI. 64 59 */ 65 60 static void *xen_grant_dma_alloc(struct device *dev, size_t size, 66 61 dma_addr_t *dma_handle, gfp_t gfp, ··· 271 276 .dma_supported = xen_grant_dma_supported, 272 277 }; 273 278 279 + bool xen_is_grant_dma_device(struct device *dev) 280 + { 281 + struct device_node *iommu_np; 282 + bool has_iommu; 283 + 284 + /* XXX Handle only DT devices for now */ 285 + if (!dev->of_node) 286 + return false; 287 + 288 + iommu_np = of_parse_phandle(dev->of_node, "iommus", 0); 289 + has_iommu = iommu_np && of_device_is_compatible(iommu_np, "xen,grant-dma"); 290 + of_node_put(iommu_np); 291 + 292 + return has_iommu; 293 + } 294 + 274 295 void xen_grant_setup_dma_ops(struct device *dev) 275 296 { 276 297 struct xen_grant_dma_data *data; 298 + struct of_phandle_args iommu_spec; 277 299 278 300 data = find_xen_grant_dma_data(dev); 279 301 if (data) { ··· 298 286 return; 299 287 } 300 288 289 + /* XXX ACPI device unsupported for now */ 290 + if (!dev->of_node) 291 + goto err; 292 + 293 + if (of_parse_phandle_with_args(dev->of_node, "iommus", "#iommu-cells", 294 + 0, &iommu_spec)) { 295 + dev_err(dev, "Cannot parse iommus property\n"); 296 + goto err; 297 + } 298 + 299 + if (!of_device_is_compatible(iommu_spec.np, "xen,grant-dma") || 300 + iommu_spec.args_count != 1) { 301 + dev_err(dev, "Incompatible IOMMU node\n"); 302 + of_node_put(iommu_spec.np); 303 + goto err; 304 + } 305 + 306 + of_node_put(iommu_spec.np); 307 + 301 308 data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL); 302 309 if (!data) 303 310 goto err; 304 311 305 - /* XXX The dom0 is hardcoded as the backend domain for now */ 306 - data->backend_domid = 0; 312 + /* 313 + * The endpoint ID here means the ID of the domain where the corresponding 314 + * backend is running 315 + */ 316 + data->backend_domid = iommu_spec.args[0]; 307 317 308 318 if (xa_err(xa_store(&xen_grant_dma_devices, (unsigned long)dev, data, 309 319 GFP_KERNEL))) {
+5
include/xen/xen-ops.h
··· 216 216 217 217 #ifdef CONFIG_XEN_GRANT_DMA_OPS 218 218 void xen_grant_setup_dma_ops(struct device *dev); 219 + bool xen_is_grant_dma_device(struct device *dev); 219 220 #else 220 221 static inline void xen_grant_setup_dma_ops(struct device *dev) 221 222 { 223 + } 224 + static inline bool xen_is_grant_dma_device(struct device *dev) 225 + { 226 + return false; 222 227 } 223 228 #endif /* CONFIG_XEN_GRANT_DMA_OPS */ 224 229