• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * Copyright (C) 2022 - Google LLC
4  * Author: David Brazdil <dbrazdil@google.com>
5  */
6 
7 #include <linux/kvm_host.h>
8 
9 /* Did all IOMMUs register as expected. */
10 static bool finalised;
11 
dev_to_id(struct device * dev)12 static unsigned long dev_to_id(struct device *dev)
13 {
14 	/* Use the struct device pointer as a unique identifier. */
15 	return (unsigned long)dev;
16 }
17 
pkvm_iommu_driver_init(u64 drv,void * data,size_t size)18 int pkvm_iommu_driver_init(u64 drv, void *data, size_t size)
19 {
20 	return kvm_call_hyp_nvhe(__pkvm_iommu_driver_init, drv, data, size);
21 }
22 EXPORT_SYMBOL(pkvm_iommu_driver_init);
23 
pkvm_iommu_register(struct device * dev,u64 drv,phys_addr_t pa,size_t size,struct device * parent,u8 flags)24 int pkvm_iommu_register(struct device *dev, u64 drv, phys_addr_t pa,
25 			size_t size, struct device *parent, u8 flags)
26 {
27 	void *mem;
28 	int ret;
29 
30 	/*
31 	 * Hypcall to register the device. It will return -ENOMEM if it needs
32 	 * more memory. In that case allocate a page and retry.
33 	 * We assume that hyp never allocates more than a page per hypcall.
34 	 */
35 	ret = kvm_call_hyp_nvhe(__pkvm_iommu_register, dev_to_id(dev),
36 				drv, pa, size, dev_to_id(parent), flags, NULL);
37 	if (ret == -ENOMEM) {
38 		mem = (void *)__get_free_page(GFP_KERNEL);
39 		if (!mem)
40 			return -ENOMEM;
41 
42 		ret = kvm_call_hyp_nvhe(__pkvm_iommu_register, dev_to_id(dev),
43 					drv, pa, size, dev_to_id(parent), flags, mem);
44 	}
45 	return ret;
46 }
47 EXPORT_SYMBOL(pkvm_iommu_register);
48 
pkvm_iommu_suspend(struct device * dev)49 int pkvm_iommu_suspend(struct device *dev)
50 {
51 	return kvm_call_hyp_nvhe(__pkvm_iommu_pm_notify, dev_to_id(dev),
52 				 PKVM_IOMMU_PM_SUSPEND);
53 }
54 EXPORT_SYMBOL(pkvm_iommu_suspend);
55 
pkvm_iommu_resume(struct device * dev)56 int pkvm_iommu_resume(struct device *dev)
57 {
58 	return kvm_call_hyp_nvhe(__pkvm_iommu_pm_notify, dev_to_id(dev),
59 				 PKVM_IOMMU_PM_RESUME);
60 }
61 EXPORT_SYMBOL(pkvm_iommu_resume);
62 
pkvm_iommu_finalize(int err)63 int pkvm_iommu_finalize(int err)
64 {
65 	finalised = !err;
66 	return kvm_call_hyp_nvhe(__pkvm_iommu_finalize, 0);
67 }
68 EXPORT_SYMBOL_GPL(pkvm_iommu_finalize);
69 
pkvm_iommu_finalized(void)70 bool pkvm_iommu_finalized(void)
71 {
72 	return finalised;
73 }
74