You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

323 lines
9.3 KiB

  1. /***************************************************************************
  2. * Copyright (C) 2005 by Dominic Rath *
  3. * Dominic.Rath@gmx.de *
  4. * *
  5. * This program is free software; you can redistribute it and/or modify *
  6. * it under the terms of the GNU General Public License as published by *
  7. * the Free Software Foundation; either version 2 of the License, or *
  8. * (at your option) any later version. *
  9. * *
  10. * This program is distributed in the hope that it will be useful, *
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of *
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
  13. * GNU General Public License for more details. *
  14. * *
  15. * You should have received a copy of the GNU General Public License *
  16. * along with this program; if not, write to the *
  17. * Free Software Foundation, Inc., *
  18. * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
  19. ***************************************************************************/
  20. #ifdef HAVE_CONFIG_H
  21. #include "config.h"
  22. #endif
  23. #include "log.h"
  24. #include "armv4_5_mmu.h"
  25. uint32_t armv4mmu_translate_va(target_t *target, armv4_5_mmu_common_t *armv4_5_mmu, uint32_t va, int *type, uint32_t *cb, int *domain, uint32_t *ap);
  26. char* armv4_5_mmu_page_type_names[] =
  27. {
  28. "section", "large page", "small page", "tiny page"
  29. };
  30. uint32_t armv4_5_mmu_translate_va(target_t *target, armv4_5_mmu_common_t *armv4_5_mmu, uint32_t va, int *type, uint32_t *cb, int *domain, uint32_t *ap)
  31. {
  32. uint32_t first_lvl_descriptor = 0x0;
  33. uint32_t second_lvl_descriptor = 0x0;
  34. uint32_t ttb = armv4_5_mmu->get_ttb(target);
  35. armv4_5_mmu_read_physical(target, armv4_5_mmu,
  36. (ttb & 0xffffc000) | ((va & 0xfff00000) >> 18),
  37. 4, 1, (uint8_t*)&first_lvl_descriptor);
  38. first_lvl_descriptor = target_buffer_get_u32(target, (uint8_t*)&first_lvl_descriptor);
  39. LOG_DEBUG("1st lvl desc: %8.8" PRIx32 "", first_lvl_descriptor);
  40. if ((first_lvl_descriptor & 0x3) == 0)
  41. {
  42. *type = -1;
  43. LOG_ERROR("Address translation failure");
  44. return ERROR_TARGET_TRANSLATION_FAULT;
  45. }
  46. if (!armv4_5_mmu->has_tiny_pages && ((first_lvl_descriptor & 0x3) == 3))
  47. {
  48. *type = -1;
  49. LOG_ERROR("Address translation failure");
  50. return ERROR_TARGET_TRANSLATION_FAULT;
  51. }
  52. /* domain is always specified in bits 8-5 */
  53. *domain = (first_lvl_descriptor & 0x1e0) >> 5;
  54. if ((first_lvl_descriptor & 0x3) == 2)
  55. {
  56. /* section descriptor */
  57. *type = ARMV4_5_SECTION;
  58. *cb = (first_lvl_descriptor & 0xc) >> 2;
  59. *ap = (first_lvl_descriptor & 0xc00) >> 10;
  60. return (first_lvl_descriptor & 0xfff00000) | (va & 0x000fffff);
  61. }
  62. if ((first_lvl_descriptor & 0x3) == 1)
  63. {
  64. /* coarse page table */
  65. armv4_5_mmu_read_physical(target, armv4_5_mmu,
  66. (first_lvl_descriptor & 0xfffffc00) | ((va & 0x000ff000) >> 10),
  67. 4, 1, (uint8_t*)&second_lvl_descriptor);
  68. }
  69. else if ((first_lvl_descriptor & 0x3) == 3)
  70. {
  71. /* fine page table */
  72. armv4_5_mmu_read_physical(target, armv4_5_mmu,
  73. (first_lvl_descriptor & 0xfffff000) | ((va & 0x000ffc00) >> 8),
  74. 4, 1, (uint8_t*)&second_lvl_descriptor);
  75. }
  76. second_lvl_descriptor = target_buffer_get_u32(target, (uint8_t*)&second_lvl_descriptor);
  77. LOG_DEBUG("2nd lvl desc: %8.8" PRIx32 "", second_lvl_descriptor);
  78. if ((second_lvl_descriptor & 0x3) == 0)
  79. {
  80. *type = -1;
  81. LOG_ERROR("Address translation failure");
  82. return ERROR_TARGET_TRANSLATION_FAULT;
  83. }
  84. /* cacheable/bufferable is always specified in bits 3-2 */
  85. *cb = (second_lvl_descriptor & 0xc) >> 2;
  86. if ((second_lvl_descriptor & 0x3) == 1)
  87. {
  88. /* large page descriptor */
  89. *type = ARMV4_5_LARGE_PAGE;
  90. *ap = (second_lvl_descriptor & 0xff0) >> 4;
  91. return (second_lvl_descriptor & 0xffff0000) | (va & 0x0000ffff);
  92. }
  93. if ((second_lvl_descriptor & 0x3) == 2)
  94. {
  95. /* small page descriptor */
  96. *type = ARMV4_5_SMALL_PAGE;
  97. *ap = (second_lvl_descriptor & 0xff0) >> 4;
  98. return (second_lvl_descriptor & 0xfffff000) | (va & 0x00000fff);
  99. }
  100. if ((second_lvl_descriptor & 0x3) == 3)
  101. {
  102. /* tiny page descriptor */
  103. *type = ARMV4_5_TINY_PAGE;
  104. *ap = (second_lvl_descriptor & 0x30) >> 4;
  105. return (second_lvl_descriptor & 0xfffffc00) | (va & 0x000003ff);
  106. }
  107. /* should not happen */
  108. *type = -1;
  109. LOG_ERROR("Address translation failure");
  110. return ERROR_TARGET_TRANSLATION_FAULT;
  111. }
  112. int armv4_5_mmu_read_physical(target_t *target, armv4_5_mmu_common_t *armv4_5_mmu, uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer)
  113. {
  114. int retval;
  115. if (target->state != TARGET_HALTED)
  116. return ERROR_TARGET_NOT_HALTED;
  117. /* disable MMU and data (or unified) cache */
  118. armv4_5_mmu->disable_mmu_caches(target, 1, 1, 0);
  119. retval = armv4_5_mmu->read_memory(target, address, size, count, buffer);
  120. /* reenable MMU / cache */
  121. armv4_5_mmu->enable_mmu_caches(target, armv4_5_mmu->mmu_enabled,
  122. armv4_5_mmu->armv4_5_cache.d_u_cache_enabled,
  123. armv4_5_mmu->armv4_5_cache.i_cache_enabled);
  124. return retval;
  125. }
  126. int armv4_5_mmu_write_physical(target_t *target, armv4_5_mmu_common_t *armv4_5_mmu, uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer)
  127. {
  128. int retval;
  129. if (target->state != TARGET_HALTED)
  130. return ERROR_TARGET_NOT_HALTED;
  131. /* disable MMU and data (or unified) cache */
  132. armv4_5_mmu->disable_mmu_caches(target, 1, 1, 0);
  133. retval = armv4_5_mmu->write_memory(target, address, size, count, buffer);
  134. /* reenable MMU / cache */
  135. armv4_5_mmu->enable_mmu_caches(target, armv4_5_mmu->mmu_enabled,
  136. armv4_5_mmu->armv4_5_cache.d_u_cache_enabled,
  137. armv4_5_mmu->armv4_5_cache.i_cache_enabled);
  138. return retval;
  139. }
  140. int armv4_5_mmu_handle_md_phys_command(command_context_t *cmd_ctx, char *cmd, char **args, int argc, target_t *target, armv4_5_mmu_common_t *armv4_5_mmu)
  141. {
  142. int count = 1;
  143. int size = 4;
  144. uint32_t address = 0;
  145. int i;
  146. char output[128];
  147. int output_len;
  148. int retval;
  149. uint8_t *buffer;
  150. if (target->state != TARGET_HALTED)
  151. {
  152. command_print(cmd_ctx, "target must be stopped for \"%s\" command", cmd);
  153. return ERROR_OK;
  154. }
  155. if (argc < 1)
  156. return ERROR_OK;
  157. if (argc == 2)
  158. count = strtoul(args[1], NULL, 0);
  159. address = strtoul(args[0], NULL, 0);
  160. switch (cmd[2])
  161. {
  162. case 'w':
  163. size = 4;
  164. break;
  165. case 'h':
  166. size = 2;
  167. break;
  168. case 'b':
  169. size = 1;
  170. break;
  171. default:
  172. return ERROR_OK;
  173. }
  174. buffer = calloc(count, size);
  175. if ((retval = armv4_5_mmu_read_physical(target, armv4_5_mmu, address, size, count, buffer)) != ERROR_OK)
  176. {
  177. switch (retval)
  178. {
  179. case ERROR_TARGET_UNALIGNED_ACCESS:
  180. command_print(cmd_ctx, "error: address not aligned");
  181. break;
  182. case ERROR_TARGET_NOT_HALTED:
  183. command_print(cmd_ctx, "error: target must be halted for memory accesses");
  184. break;
  185. case ERROR_TARGET_DATA_ABORT:
  186. command_print(cmd_ctx, "error: access caused data abort, system possibly corrupted");
  187. break;
  188. default:
  189. command_print(cmd_ctx, "error: unknown error");
  190. }
  191. }
  192. output_len = 0;
  193. for (i = 0; i < count; i++)
  194. {
  195. if (i%8 == 0)
  196. output_len += snprintf(output + output_len, 128 - output_len, "0x%8.8" PRIx32 ": ", address + (i*size));
  197. switch (size)
  198. {
  199. case 4:
  200. output_len += snprintf(output + output_len, 128 - output_len, "%8.8" PRIx32 " ", target_buffer_get_u32(target, &buffer[i*4]));
  201. break;
  202. case 2:
  203. output_len += snprintf(output + output_len, 128 - output_len, "%4.4x ", target_buffer_get_u16(target, &buffer[i*2]));
  204. break;
  205. case 1:
  206. output_len += snprintf(output + output_len, 128 - output_len, "%2.2x ", buffer[i*1]);
  207. break;
  208. }
  209. if ((i % 8 == 7) || (i == count - 1))
  210. {
  211. command_print(cmd_ctx, "%s", output);
  212. output_len = 0;
  213. }
  214. }
  215. free(buffer);
  216. return ERROR_OK;
  217. }
  218. int armv4_5_mmu_handle_mw_phys_command(command_context_t *cmd_ctx, char *cmd, char **args, int argc, target_t *target, armv4_5_mmu_common_t *armv4_5_mmu)
  219. {
  220. uint32_t address = 0;
  221. uint32_t value = 0;
  222. int retval;
  223. uint8_t value_buf[4];
  224. if (target->state != TARGET_HALTED)
  225. {
  226. command_print(cmd_ctx, "target must be stopped for \"%s\" command", cmd);
  227. return ERROR_OK;
  228. }
  229. if (argc < 2)
  230. return ERROR_OK;
  231. address = strtoul(args[0], NULL, 0);
  232. value = strtoul(args[1], NULL, 0);
  233. switch (cmd[2])
  234. {
  235. case 'w':
  236. target_buffer_set_u32(target, value_buf, value);
  237. retval = armv4_5_mmu_write_physical(target, armv4_5_mmu, address, 4, 1, value_buf);
  238. break;
  239. case 'h':
  240. target_buffer_set_u16(target, value_buf, value);
  241. retval = armv4_5_mmu_write_physical(target, armv4_5_mmu, address, 2, 1, value_buf);
  242. break;
  243. case 'b':
  244. value_buf[0] = value;
  245. retval = armv4_5_mmu_write_physical(target, armv4_5_mmu, address, 1, 1, value_buf);
  246. break;
  247. default:
  248. return ERROR_OK;
  249. }
  250. switch (retval)
  251. {
  252. case ERROR_TARGET_UNALIGNED_ACCESS:
  253. command_print(cmd_ctx, "error: address not aligned");
  254. break;
  255. case ERROR_TARGET_DATA_ABORT:
  256. command_print(cmd_ctx, "error: access caused data abort, system possibly corrupted");
  257. break;
  258. case ERROR_TARGET_NOT_HALTED:
  259. command_print(cmd_ctx, "error: target must be halted for memory accesses");
  260. break;
  261. case ERROR_OK:
  262. break;
  263. default:
  264. command_print(cmd_ctx, "error: unknown error");
  265. }
  266. return ERROR_OK;
  267. }