pte_stuff.h 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195
  1. //
  2. // pte_stuff.h
  3. // extra_recipe
  4. //
  5. // Copyright © 2017 xerub. All rights reserved.
  6. // Copyright © 2017 qwertyoruiop. All rights reserved.
  7. //
  8. #ifndef pte_stuff_h
  9. #define pte_stuff_h
  10. #define TTE_INDEX_SHIFT 3
  11. #define TTE_SIZE (1 << TTE_INDEX_SHIFT)
  12. #define TTE_INDEX(vma, level) ((vma.vm_info.level ## _index) << TTE_INDEX_SHIFT)
  13. #define TTE_GET(tte, mask) (tte & mask)
  14. #define TTE_SETB(tte, mask) tte = tte | mask
  15. #define TTE_SET(tte, mask, val) tte = ((tte & (~mask)) | (val & mask))
  16. #define TTE_IS_VALID_MASK 0x1
  17. #define TTE_IS_TABLE_MASK 0x2
  18. #define TTE_BLOCK_ATTR_INDEX_MASK 0x1C
  19. #define TTE_BLOCK_ATTR_NS_MASK 0x20
  20. #define TTE_BLOCK_ATTR_AP_MASK 0xC0
  21. #define TTE_BLOCK_ATTR_AP_RO_MASK 0x80
  22. #define TTE_BLOCK_ATTR_AP_CAN_EL0_ACCESS_MASK 0x40
  23. #define TTE_BLOCK_ATTR_SH_MASK 0x300
  24. #define TTE_BLOCK_ATTR_AF_MASK 0x400
  25. #define TTE_BLOCK_ATTR_NG_MASK 0x800
  26. #define TTE_PHYS_VALUE_MASK 0xFFFFFFFFF000ULL
  27. #define TTE_BLOCK_ATTR_CONTIG_MASK (1ULL << 52)
  28. #define TTE_BLOCK_ATTR_PXN_MASK (1ULL << 53)
  29. #define TTE_BLOCK_ATTR_UXN_MASK (1ULL << 54)
  30. #define VIRT_TO_PHYS(vaddr) (vaddr - gVirtBase + gPhysBase)
  31. #define PHYS_TO_VIRT(paddr) (paddr - gPhysBase + gVirtBase)
  32. uint64_t gPhysBase,gVirtBase,pmap_store,level1_table,hibit_guess;
  33. typedef union VMA_4K {
  34. struct {
  35. uint64_t block_off : 12;
  36. uint64_t level3_index : 9;
  37. uint64_t level2_index : 9;
  38. uint64_t level1_index : 9;
  39. uint64_t level0_index : 9;
  40. uint64_t ttbr_selector : 16;
  41. } __attribute__((packed)) vm_info;
  42. uint64_t vmaddr;
  43. } VMA_4K;
  44. typedef union VMA_16K {
  45. struct {
  46. uint64_t block_off : 14;
  47. uint64_t level3_index : 11;
  48. uint64_t level2_index : 11;
  49. uint64_t level1_index : 11;
  50. uint64_t level0_index : 1;
  51. uint64_t ttbr_selector : 16;
  52. } __attribute__((packed)) vm_info;
  53. uint64_t vmaddr;
  54. } VMA_16K;
  55. VMA_16K vad16;
  56. VMA_4K vad4;
  57. char isvad = 0;
  58. #define TTELog NSLog
  59. vm_size_t sz = 0;
  60. void checkvad() {
  61. if (!sz) {
  62. struct utsname u = { 0 };
  63. uname(&u);
  64. host_page_size(mach_host_self(), &sz);
  65. printf("[INFO]: checkvad: %lx %x\n", sz, getpagesize());
  66. if (strstr(u.machine, "AppleTV5,") == u.machine) {
  67. sz = 4096; // this is 4k but host_page_size lies to us
  68. }
  69. assert(sz);
  70. if (sz == 4096) {
  71. isvad = 1;
  72. }
  73. }
  74. }
  75. void parse_block_tte(uint64_t tte) {
  76. TTELog(@"TTE physaddr: %016llx", TTE_GET(tte, TTE_PHYS_VALUE_MASK));
  77. TTELog(@"TTE table: %d", !!(TTE_GET(tte, TTE_IS_TABLE_MASK)));
  78. TTELog(@"TTE valid: %d", !!(TTE_GET(tte, TTE_IS_VALID_MASK)));
  79. TTELog(@"TTE userland eXecute Never: %d", !!(TTE_GET(tte, TTE_BLOCK_ATTR_UXN_MASK)));
  80. TTELog(@"TTE privileged eXecute Never: %d", !!(TTE_GET(tte, TTE_BLOCK_ATTR_PXN_MASK)));
  81. TTELog(@"TTE contiguous: %d", !!(TTE_GET(tte, TTE_BLOCK_ATTR_CONTIG_MASK)));
  82. TTELog(@"TTE not global: %d", !!(TTE_GET(tte, TTE_BLOCK_ATTR_NG_MASK)));
  83. TTELog(@"TTE access flag: %d", !!(TTE_GET(tte, TTE_BLOCK_ATTR_AF_MASK)));
  84. TTELog(@"TTE shareable: %01llx", (TTE_GET(tte, TTE_BLOCK_ATTR_SH_MASK) >> 8));
  85. TTELog(@"TTE access permissions: %s", (TTE_GET(tte, TTE_BLOCK_ATTR_AP_RO_MASK)) ? "Read only" : "Read/Write");
  86. TTELog(@"TTE access permissions: %s", (TTE_GET(tte, TTE_BLOCK_ATTR_AP_CAN_EL0_ACCESS_MASK)) ? "EL0 (Userland) can access this page" : "EL0 (Userland) cannot access this page");
  87. }
  88. void pagestuff_64(vm_address_t vmaddr, void (^pagestuff_64_callback)(vm_address_t tte_addr, int addr), vm_address_t table, int level) {
  89. checkvad();
  90. if (!table) table = level1_table;
  91. if (!level) level = 1;
  92. vm_address_t tteaddr = 0;
  93. if (sz == 4096) {
  94. VMA_4K target_addr;
  95. target_addr.vmaddr = vmaddr;
  96. if (level == 1) {
  97. target_addr.vm_info.level1_index -= 0x1c0;
  98. }
  99. switch (level) {
  100. case 0:
  101. tteaddr = table + TTE_INDEX(target_addr, level0);
  102. break;
  103. case 1:
  104. tteaddr = table + TTE_INDEX(target_addr, level1);
  105. break;
  106. case 2:
  107. tteaddr = table + TTE_INDEX(target_addr, level2);
  108. break;
  109. case 3:
  110. tteaddr = table + TTE_INDEX(target_addr, level3);
  111. break;
  112. default:
  113. break;
  114. }
  115. } else if (sz == 4096*4) {
  116. VMA_16K target_addr;
  117. target_addr.vmaddr = vmaddr;
  118. switch (level) {
  119. case 0:
  120. tteaddr = table + TTE_INDEX(target_addr, level0);
  121. break;
  122. case 1:
  123. tteaddr = table + TTE_INDEX(target_addr, level1);
  124. break;
  125. case 2:
  126. tteaddr = table + TTE_INDEX(target_addr, level2);
  127. break;
  128. case 3:
  129. tteaddr = table + TTE_INDEX(target_addr, level3);
  130. break;
  131. default:
  132. break;
  133. }
  134. }
  135. //parse_block_tte(level1_entry);
  136. pagestuff_64_callback(tteaddr, level);
  137. uint64_t level1_entry = ReadAnywhere64(tteaddr);
  138. if (TTE_GET(level1_entry, TTE_IS_TABLE_MASK) && level != 3) {
  139. pagestuff_64(vmaddr, pagestuff_64_callback, (TTE_GET(level1_entry, TTE_PHYS_VALUE_MASK)) - gPhysBase + gVirtBase, level + 1);
  140. }
  141. }
  142. uint64_t findphys_real(uint64_t virtaddr) {
  143. __block uint64_t physvar = 0;
  144. pagestuff_64(virtaddr, ^(vm_address_t tte_addr, int addr) {
  145. uint64_t tte = ReadAnywhere64(tte_addr);
  146. if (addr == 3) {\
  147. physvar = TTE_GET(tte, TTE_PHYS_VALUE_MASK);
  148. }
  149. }, level1_table, isvad ? 1 : 2);
  150. return physvar;
  151. }
  152. extern task_t tfp0;
  153. uint64_t physalloc(uint64_t size) {
  154. uint64_t ret = 0;
  155. mach_vm_allocate(tfp0, (mach_vm_address_t*) &ret, size, VM_FLAGS_ANYWHERE);
  156. return ret;
  157. }
  158. #endif