trusty-mem.c 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. /*
  2. * Copyright (C) 2015 Google, Inc.
  3. *
  4. * This software is licensed under the terms of the GNU General Public
  5. * License version 2, as published by the Free Software Foundation, and
  6. * may be copied, distributed, and modified under those terms.
  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/types.h>
  15. #include <linux/printk.h>
  16. #include <linux/trusty/trusty.h>
  17. #include <linux/trusty/smcall.h>
  18. static int get_mem_attr(struct page *page, pgprot_t pgprot)
  19. {
  20. #if defined(CONFIG_ARM64)
  21. uint64_t mair;
  22. uint attr_index = (pgprot_val(pgprot) & PTE_ATTRINDX_MASK) >> 2;
  23. asm ("mrs %0, mair_el1\n" : "=&r" (mair));
  24. return (mair >> (attr_index * 8)) & 0xff;
  25. #elif defined(CONFIG_ARM_LPAE)
  26. uint32_t mair;
  27. uint attr_index = ((pgprot_val(pgprot) & L_PTE_MT_MASK) >> 2);
  28. if (attr_index >= 4) {
  29. attr_index -= 4;
  30. asm volatile("mrc p15, 0, %0, c10, c2, 1\n" : "=&r" (mair));
  31. } else {
  32. asm volatile("mrc p15, 0, %0, c10, c2, 0\n" : "=&r" (mair));
  33. }
  34. return (mair >> (attr_index * 8)) & 0xff;
  35. #elif defined(CONFIG_ARM)
  36. /* check memory type */
  37. switch (pgprot_val(pgprot) & L_PTE_MT_MASK) {
  38. case L_PTE_MT_WRITEALLOC:
  39. /* Normal: write back write allocate */
  40. return 0xFF;
  41. case L_PTE_MT_BUFFERABLE:
  42. /* Normal: non-cacheble */
  43. return 0x44;
  44. case L_PTE_MT_WRITEBACK:
  45. /* Normal: writeback, read allocate */
  46. return 0xEE;
  47. case L_PTE_MT_WRITETHROUGH:
  48. /* Normal: write through */
  49. return 0xAA;
  50. case L_PTE_MT_UNCACHED:
  51. /* strongly ordered */
  52. return 0x00;
  53. case L_PTE_MT_DEV_SHARED:
  54. case L_PTE_MT_DEV_NONSHARED:
  55. /* device */
  56. return 0x04;
  57. default:
  58. return -EINVAL;
  59. }
  60. #else
  61. return 0;
  62. #endif
  63. }
  64. int trusty_encode_page_info(struct ns_mem_page_info *inf,
  65. struct page *page, pgprot_t pgprot)
  66. {
  67. int mem_attr;
  68. uint64_t pte;
  69. if (!inf || !page)
  70. return -EINVAL;
  71. /* get physical address */
  72. pte = (uint64_t) page_to_phys(page);
  73. /* get memory attributes */
  74. mem_attr = get_mem_attr(page, pgprot);
  75. if (mem_attr < 0)
  76. return mem_attr;
  77. /* add other attributes */
  78. #if defined(CONFIG_ARM64) || defined(CONFIG_ARM_LPAE)
  79. pte |= pgprot_val(pgprot);
  80. #elif defined(CONFIG_ARM)
  81. if (pgprot_val(pgprot) & L_PTE_USER)
  82. pte |= (1 << 6);
  83. if (pgprot_val(pgprot) & L_PTE_RDONLY)
  84. pte |= (1 << 7);
  85. if (pgprot_val(pgprot) & L_PTE_SHARED)
  86. pte |= (3 << 8); /* inner sharable */
  87. #endif
  88. inf->attr = (pte & 0x0000FFFFFFFFFFFFull) | ((uint64_t)mem_attr << 48);
  89. return 0;
  90. }
  91. int trusty_call32_mem_buf(struct device *dev, u32 smcnr,
  92. struct page *page, u32 size,
  93. pgprot_t pgprot)
  94. {
  95. int ret;
  96. struct ns_mem_page_info pg_inf;
  97. if (!dev || !page)
  98. return -EINVAL;
  99. ret = trusty_encode_page_info(&pg_inf, page, pgprot);
  100. if (ret)
  101. return ret;
  102. if (SMC_IS_FASTCALL(smcnr)) {
  103. return trusty_fast_call32(dev, smcnr,
  104. (u32)pg_inf.attr,
  105. (u32)(pg_inf.attr >> 32), size);
  106. } else {
  107. return trusty_std_call32(dev, smcnr,
  108. (u32)pg_inf.attr,
  109. (u32)(pg_inf.attr >> 32), size);
  110. }
  111. }