armmmu_translate.c 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include "KEHeader.h"
  5. extern uint64_t get_mpt(void);
  6. extern uint64_t kedump_mem_read(uint64_t data, unsigned long sz, void *buf);
  7. #if 0
  8. extern int sLOG(char *fmt, ...);
  9. #define LOG(fmt, ...) \
  10. do { \
  11. sLOG(fmt, ##__VA_ARGS__); \
  12. printf(fmt, ##__VA_ARGS__); \
  13. } while(0)
  14. #else
  15. #define LOG(fmt, ...)
  16. #endif
  17. static int read_mem(uint64_t paddr, void *buf, unsigned long size)
  18. {
  19. uint64_t ret = 0;
  20. ret = kedump_mem_read(paddr, size, buf);
  21. return (ret == size) ? 0 : -1;
  22. }
  23. #define PAGE_SIZE 4096
  24. #define PNUM_64 (PAGE_SIZE / sizeof(uint64_t))
  25. static uint64_t lxpage[PNUM_64];
  26. /* ARM PGD/PMD first 3 pages for userspace, last 1 pages for kernel space */
  27. #define PNUM_32 (PAGE_SIZE * 4 / sizeof(uint32_t))
  28. static uint32_t l1page32[PNUM_32];
  29. /* ARM L2 PTE 512 entry and each entry 4 bytes */
  30. #define PNUM_L2_32 512
  31. static uint32_t l2page32[PNUM_L2_32];
  32. static uint64_t mmutable_64_translate_l3(uint64_t vptr,
  33. uint64_t ptable)
  34. {
  35. int ret = 0;
  36. uint64_t pa;
  37. unsigned int lxidx = (vptr >> 12) & 0x1ff;
  38. if (lxidx >= PNUM_64) {
  39. LOG("address:0x%llx index:%d overflow error\n", vptr, lxidx);
  40. return 0;
  41. }
  42. memset(lxpage, 0, PAGE_SIZE);
  43. ret = read_mem(ptable, lxpage, PAGE_SIZE);
  44. if (ret == 0) {
  45. LOG("(%d)ent value:0x%llx\n", lxidx, lxpage[lxidx]);
  46. } else {
  47. return 0;
  48. }
  49. switch(lxpage[lxidx] & 3) {
  50. case 3:
  51. pa = (lxpage[lxidx] & 0x0000fffffffff000)
  52. + (vptr & 0xfff);
  53. break;
  54. default:
  55. LOG("invalid (%d)ent value:0x%llx\n", lxidx,
  56. lxpage[lxidx]);
  57. pa = 0;
  58. }
  59. return pa;
  60. }
  61. static uint64_t mmutable_64_translate_l2(uint64_t vptr,
  62. uint64_t ptable)
  63. {
  64. int ret = 0;
  65. uint64_t pa;
  66. uint64_t next_table_address;
  67. unsigned int lxidx = (vptr >> 21) & 0x1ff;
  68. if (lxidx >= PNUM_64) {
  69. LOG("address:0x%llx index:%d overflow error\n", vptr, lxidx);
  70. return 0;
  71. }
  72. memset(lxpage, 0, PAGE_SIZE);
  73. ret = read_mem(ptable, lxpage, PAGE_SIZE);
  74. if (ret == 0) {
  75. LOG("(%d)ent value:0x%llx\n", lxidx, lxpage[lxidx]);
  76. } else {
  77. return 0;
  78. }
  79. switch(lxpage[lxidx] & 3) {
  80. case 1:
  81. pa = (lxpage[lxidx] & 0x0000ffffffe00000)
  82. + (vptr & 0x1fffff);
  83. break;
  84. case 3:
  85. next_table_address = lxpage[lxidx]
  86. & 0x0000fffffffff000;
  87. pa = mmutable_64_translate_l3(vptr,
  88. next_table_address);
  89. break;
  90. default:
  91. LOG("invalid (%d)ent value:0x%llx\n", lxidx,
  92. lxpage[lxidx]);
  93. pa = 0;
  94. }
  95. return pa;
  96. }
  97. static uint64_t mmutable_64_translate_l1(uint64_t vptr,
  98. uint64_t ptable)
  99. {
  100. int ret = 0;
  101. uint64_t pa;
  102. uint64_t next_table_address;
  103. unsigned int lxidx = (vptr >> 30) & 0x1ff;
  104. if (lxidx >= PNUM_64) {
  105. LOG("address:0x%llx index:%d overflow error\n", vptr, lxidx);
  106. return 0;
  107. }
  108. memset(lxpage, 0, PAGE_SIZE);
  109. ret = read_mem(ptable, lxpage, PAGE_SIZE);
  110. if (ret == 0) {
  111. LOG("(%d)ent value:0x%llx\n", lxidx, lxpage[lxidx]);
  112. } else {
  113. return 0;
  114. }
  115. switch(lxpage[lxidx] & 3) {
  116. case 1:
  117. pa = (lxpage[lxidx] & 0x0000ffffc0000000)
  118. + (vptr & 0x3fffffff);
  119. break;
  120. case 3:
  121. next_table_address = lxpage[lxidx]
  122. & 0x0000fffffffff000;
  123. pa = mmutable_64_translate_l2(vptr,
  124. next_table_address);
  125. break;
  126. default:
  127. LOG("invalid (%d)ent value:0x%llx\n", lxidx,
  128. lxpage[lxidx]);
  129. pa = 0;
  130. }
  131. return pa;
  132. }
  133. uint64_t v2p_64(uint64_t vptr)
  134. {
  135. uint64_t mpt = get_mpt();
  136. /* LOG("mater_page_table:0x%llx, vptr:0x%llx\n", mpt, vptr); */
  137. if ((vptr & 0x8000000000000000) != 0) {
  138. return mmutable_64_translate_l1(vptr, mpt);
  139. } else {
  140. LOG("illegal address:0x%llx\n", vptr);
  141. }
  142. return 0;
  143. }
  144. static uint64_t mmutable_32_translate_l2(uint64_t vptr, uint64_t ptable)
  145. {
  146. int ret;
  147. uint64_t pa = 0;
  148. unsigned int lxidx = (vptr >> 12) & 0x1ff;
  149. memset(l2page32, 0, sizeof(l2page32));
  150. ret = read_mem(ptable, l2page32, sizeof(l2page32));
  151. if (ret == 0) {
  152. LOG("(%d)ent value:0x%x\n", lxidx, l2page32[lxidx]);
  153. } else {
  154. LOG("invalid l2 page table:0x%llx\n", ptable);
  155. return 0;
  156. }
  157. if (l2page32[lxidx] & 1)
  158. pa = (l2page32[lxidx] & 0xfffff000) + (vptr & 0xfff);
  159. else
  160. LOG("invalid (%d)ent value:0x%x\n", lxidx, l2page32[lxidx]);
  161. return pa;
  162. }
  163. static uint64_t mmutable_32_translate_l1(uint64_t vptr, uint64_t ptable)
  164. {
  165. int ret;
  166. uint64_t pa;
  167. uint64_t next_table_address;
  168. unsigned int lxidx = (vptr >> 20) & 0xfff;
  169. if (lxidx >= PNUM_32) {
  170. LOG("address:0x%llx index:%d overflow error\n", vptr, lxidx);
  171. return 0;
  172. }
  173. memset(l1page32, 0, sizeof(l1page32));
  174. ret = read_mem(ptable, l1page32, sizeof(l1page32));
  175. if (ret == 0) {
  176. LOG("(%d)ent value:0x%x\n", lxidx, l1page32[lxidx]);
  177. } else {
  178. LOG("invalid l1 page table:0x%llx\n", ptable);
  179. return 0;
  180. }
  181. switch(l1page32[lxidx] & 3) {
  182. case 1:
  183. /* PMD point address is 1KB allign */
  184. next_table_address = l1page32[lxidx] & 0xfffff000;
  185. pa = mmutable_32_translate_l2(vptr, next_table_address);
  186. break;
  187. case 2:
  188. /* [31:20]12bit as PMD index */
  189. pa = (l1page32[lxidx] & 0xfff00000) + (vptr & 0xfffff);
  190. break;
  191. default:
  192. LOG("invalid (%d)ent value:0x%x\n", lxidx, l1page32[lxidx]);
  193. pa = 0;
  194. }
  195. return pa;
  196. }
  197. uint64_t v2p_32(uint64_t vptr)
  198. {
  199. uint64_t mpt = get_mpt();
  200. if (vptr > 0xbf000000) {
  201. return mmutable_32_translate_l1(vptr, mpt);
  202. } else {
  203. LOG("illegal address:0x%llx\n", vptr);
  204. }
  205. return 0;
  206. }