iommu.c 1.8 KB

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