arm-smmu-errata.c 1.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253
  1. /*
  2. * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
  3. *
  4. * This program is free software; you can redistribute it and/or modify
  5. * it under the terms of the GNU General Public License version 2 and
  6. * only version 2 as published by the Free Software Foundation.
  7. *
  8. * This program is distributed in the hope that it will be useful,
  9. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. * GNU General Public License for more details.
  12. *
  13. */
  14. #include <linux/kernel.h>
  15. #include <soc/qcom/secure_buffer.h>
  16. #include <linux/arm-smmu-errata.h>
  17. static struct page *guard_pages[VMID_LAST];
  18. static DEFINE_MUTEX(guard_page_lock);
  19. struct page *arm_smmu_errata_get_guard_page(int vmid)
  20. {
  21. struct page *page;
  22. int ret;
  23. int source_vm = VMID_HLOS;
  24. int dest_vm = vmid;
  25. int dest_perm = PERM_READ | PERM_WRITE | PERM_EXEC;
  26. size_t size = ARM_SMMU_MIN_IOVA_ALIGN;
  27. mutex_lock(&guard_page_lock);
  28. page = guard_pages[vmid];
  29. if (page)
  30. goto out;
  31. page = alloc_pages(GFP_KERNEL, get_order(size));
  32. if (!page)
  33. goto out;
  34. if (vmid != VMID_HLOS) {
  35. ret = hyp_assign_phys(page_to_phys(page), PAGE_ALIGN(size),
  36. &source_vm, 1,
  37. &dest_vm, &dest_perm, 1);
  38. if (ret && (ret != -EIO)) {
  39. __free_pages(page, get_order(size));
  40. page = NULL;
  41. }
  42. }
  43. guard_pages[vmid] = page;
  44. out:
  45. mutex_unlock(&guard_page_lock);
  46. return page;
  47. }