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.
 
 
 
 
 
 

311 lines
9.8 KiB

  1. /***************************************************************************
  2. * Copyright (C) 2013-2014,2019-2020 Synopsys, Inc. *
  3. * Frank Dols <frank.dols@synopsys.com> *
  4. * Mischa Jonker <mischa.jonker@synopsys.com> *
  5. * Anton Kolesov <anton.kolesov@synopsys.com> *
  6. * Evgeniy Didin <didin@synopsys.com> *
  7. * *
  8. * SPDX-License-Identifier: GPL-2.0-or-later *
  9. ***************************************************************************/
  10. #ifdef HAVE_CONFIG_H
  11. #include "config.h"
  12. #endif
  13. #include "arc.h"
  14. /* ----- Supporting functions ---------------------------------------------- */
  15. static bool arc_mem_is_slow_memory(struct arc_common *arc, uint32_t addr,
  16. uint32_t size, uint32_t count)
  17. {
  18. uint32_t addr_end = addr + size * count;
  19. /* `_end` field can overflow - it points to the first byte after the end,
  20. * therefore if DCCM is right at the end of memory address space, then
  21. * dccm_end will be 0. */
  22. assert(addr_end >= addr || addr_end == 0);
  23. return !((addr >= arc->dccm_start && addr_end <= arc->dccm_end) ||
  24. (addr >= arc->iccm0_start && addr_end <= arc->iccm0_end) ||
  25. (addr >= arc->iccm1_start && addr_end <= arc->iccm1_end));
  26. }
  27. /* Write word at word-aligned address */
  28. static int arc_mem_write_block32(struct target *target, uint32_t addr,
  29. uint32_t count, void *buf)
  30. {
  31. struct arc_common *arc = target_to_arc(target);
  32. LOG_DEBUG("Write 4-byte memory block: addr=0x%08" PRIx32 ", count=%" PRIu32,
  33. addr, count);
  34. /* Check arguments */
  35. assert(!(addr & 3));
  36. /* We need to flush the cache since it might contain dirty
  37. * lines, so the cache invalidation may cause data inconsistency. */
  38. CHECK_RETVAL(arc_cache_flush(target));
  39. /* No need to flush cache, because we don't read values from memory. */
  40. CHECK_RETVAL(arc_jtag_write_memory(&arc->jtag_info, addr, count,
  41. (uint32_t *)buf));
  42. /* Invalidate caches. */
  43. CHECK_RETVAL(arc_cache_invalidate(target));
  44. return ERROR_OK;
  45. }
  46. /* Write half-word at half-word-aligned address */
  47. static int arc_mem_write_block16(struct target *target, uint32_t addr,
  48. uint32_t count, void *buf)
  49. {
  50. struct arc_common *arc = target_to_arc(target);
  51. uint32_t i;
  52. uint32_t buffer_he;
  53. uint8_t buffer_te[sizeof(uint32_t)];
  54. uint8_t halfword_te[sizeof(uint16_t)];
  55. LOG_DEBUG("Write 2-byte memory block: addr=0x%08" PRIx32 ", count=%" PRIu32,
  56. addr, count);
  57. /* Check arguments */
  58. assert(!(addr & 1));
  59. /* We will read data from memory, so we need to flush the cache. */
  60. CHECK_RETVAL(arc_cache_flush(target));
  61. /* non-word writes are less common than 4-byte writes, so I suppose we can
  62. * allow ourselves to write this in a cycle, instead of calling arc_jtag
  63. * with count > 1. */
  64. for (i = 0; i < count; i++) {
  65. /* We can read only word at word-aligned address. Also *jtag_read_memory
  66. * functions return data in host endianness, so host endianness !=
  67. * target endianness we have to convert data back to target endianness,
  68. * or bytes will be at the wrong places.So:
  69. * 1) read word
  70. * 2) convert to target endianness
  71. * 3) make changes
  72. * 4) convert back to host endianness
  73. * 5) write word back to target.
  74. */
  75. bool is_slow_memory = arc_mem_is_slow_memory(arc,
  76. (addr + i * sizeof(uint16_t)) & ~3u, 4, 1);
  77. CHECK_RETVAL(arc_jtag_read_memory(&arc->jtag_info,
  78. (addr + i * sizeof(uint16_t)) & ~3u, 1, &buffer_he,
  79. is_slow_memory));
  80. target_buffer_set_u32(target, buffer_te, buffer_he);
  81. /* buf is in host endianness, convert to target */
  82. target_buffer_set_u16(target, halfword_te, ((uint16_t *)buf)[i]);
  83. memcpy(buffer_te + ((addr + i * sizeof(uint16_t)) & 3u),
  84. halfword_te, sizeof(uint16_t));
  85. buffer_he = target_buffer_get_u32(target, buffer_te);
  86. CHECK_RETVAL(arc_jtag_write_memory(&arc->jtag_info,
  87. (addr + i * sizeof(uint16_t)) & ~3u, 1, &buffer_he));
  88. }
  89. /* Invalidate caches. */
  90. CHECK_RETVAL(arc_cache_invalidate(target));
  91. return ERROR_OK;
  92. }
  93. /* Write byte at address */
  94. static int arc_mem_write_block8(struct target *target, uint32_t addr,
  95. uint32_t count, void *buf)
  96. {
  97. struct arc_common *arc = target_to_arc(target);
  98. uint32_t i;
  99. uint32_t buffer_he;
  100. uint8_t buffer_te[sizeof(uint32_t)];
  101. LOG_DEBUG("Write 1-byte memory block: addr=0x%08" PRIx32 ", count=%" PRIu32,
  102. addr, count);
  103. /* We will read data from memory, so we need to flush the cache. */
  104. CHECK_RETVAL(arc_cache_flush(target));
  105. /* non-word writes are less common than 4-byte writes, so I suppose we can
  106. * allow ourselves to write this in a cycle, instead of calling arc_jtag
  107. * with count > 1. */
  108. for (i = 0; i < count; i++) {
  109. /* See comment in arc_mem_write_block16 for details. Since it is a byte
  110. * there is not need to convert write buffer to target endianness, but
  111. * we still have to convert read buffer. */
  112. CHECK_RETVAL(arc_jtag_read_memory(&arc->jtag_info, (addr + i) & ~3, 1, &buffer_he,
  113. arc_mem_is_slow_memory(arc, (addr + i) & ~3, 4, 1)));
  114. target_buffer_set_u32(target, buffer_te, buffer_he);
  115. memcpy(buffer_te + ((addr + i) & 3), (uint8_t *)buf + i, 1);
  116. buffer_he = target_buffer_get_u32(target, buffer_te);
  117. CHECK_RETVAL(arc_jtag_write_memory(&arc->jtag_info, (addr + i) & ~3, 1, &buffer_he));
  118. }
  119. /* Invalidate caches. */
  120. CHECK_RETVAL(arc_cache_invalidate(target));
  121. return ERROR_OK;
  122. }
  123. /* ----- Exported functions ------------------------------------------------ */
  124. int arc_mem_write(struct target *target, target_addr_t address, uint32_t size,
  125. uint32_t count, const uint8_t *buffer)
  126. {
  127. int retval = ERROR_OK;
  128. void *tunnel = NULL;
  129. LOG_DEBUG("address: 0x%08" TARGET_PRIxADDR ", size: %" PRIu32 ", count: %" PRIu32,
  130. address, size, count);
  131. if (target->state != TARGET_HALTED) {
  132. LOG_WARNING("target not halted");
  133. return ERROR_TARGET_NOT_HALTED;
  134. }
  135. /* sanitize arguments */
  136. if (((size != 4) && (size != 2) && (size != 1)) || !(count) || !(buffer))
  137. return ERROR_COMMAND_SYNTAX_ERROR;
  138. if (((size == 4) && (address & 0x3u)) || ((size == 2) && (address & 0x1u)))
  139. return ERROR_TARGET_UNALIGNED_ACCESS;
  140. /* correct endianness if we have word or hword access */
  141. if (size > 1) {
  142. /*
  143. * arc_..._write_mem with size 4/2 requires uint32_t/uint16_t
  144. * in host endianness, but byte array represents target endianness.
  145. */
  146. tunnel = calloc(1, count * size * sizeof(uint8_t));
  147. if (!tunnel) {
  148. LOG_ERROR("Unable to allocate memory");
  149. return ERROR_FAIL;
  150. }
  151. switch (size) {
  152. case 4:
  153. target_buffer_get_u32_array(target, buffer, count,
  154. (uint32_t *)tunnel);
  155. break;
  156. case 2:
  157. target_buffer_get_u16_array(target, buffer, count,
  158. (uint16_t *)tunnel);
  159. break;
  160. }
  161. buffer = tunnel;
  162. }
  163. if (size == 4) {
  164. retval = arc_mem_write_block32(target, address, count, (void *)buffer);
  165. } else if (size == 2) {
  166. /* We convert buffer from host endianness to target. But then in
  167. * write_block16, we do the reverse. Is there a way to avoid this without
  168. * breaking other cases? */
  169. retval = arc_mem_write_block16(target, address, count, (void *)buffer);
  170. } else {
  171. retval = arc_mem_write_block8(target, address, count, (void *)buffer);
  172. }
  173. free(tunnel);
  174. return retval;
  175. }
  176. static int arc_mem_read_block(struct target *target, target_addr_t addr,
  177. uint32_t size, uint32_t count, void *buf)
  178. {
  179. struct arc_common *arc = target_to_arc(target);
  180. LOG_DEBUG("Read memory: addr=0x%08" TARGET_PRIxADDR ", size=%" PRIu32
  181. ", count=%" PRIu32, addr, size, count);
  182. assert(!(addr & 3));
  183. assert(size == 4);
  184. /* Flush cache before memory access */
  185. CHECK_RETVAL(arc_cache_flush(target));
  186. CHECK_RETVAL(arc_jtag_read_memory(&arc->jtag_info, addr, count, buf,
  187. arc_mem_is_slow_memory(arc, addr, size, count)));
  188. return ERROR_OK;
  189. }
  190. int arc_mem_read(struct target *target, target_addr_t address, uint32_t size,
  191. uint32_t count, uint8_t *buffer)
  192. {
  193. int retval = ERROR_OK;
  194. void *tunnel_he;
  195. uint8_t *tunnel_te;
  196. uint32_t words_to_read, bytes_to_read;
  197. LOG_DEBUG("Read memory: addr=0x%08" TARGET_PRIxADDR ", size=%" PRIu32
  198. ", count=%" PRIu32, address, size, count);
  199. if (target->state != TARGET_HALTED) {
  200. LOG_WARNING("target not halted");
  201. return ERROR_TARGET_NOT_HALTED;
  202. }
  203. /* Sanitize arguments */
  204. if (((size != 4) && (size != 2) && (size != 1)) || !(count) || !(buffer))
  205. return ERROR_COMMAND_SYNTAX_ERROR;
  206. if (((size == 4) && (address & 0x3u)) || ((size == 2) && (address & 0x1u)))
  207. return ERROR_TARGET_UNALIGNED_ACCESS;
  208. /* Reads are word-aligned, so padding might be required if count > 1.
  209. * NB: +3 is a padding for the last word (in case it's not aligned;
  210. * addr&3 is a padding for the first word (since address can be
  211. * unaligned as well). */
  212. bytes_to_read = (count * size + 3 + (address & 3u)) & ~3u;
  213. words_to_read = bytes_to_read >> 2;
  214. tunnel_he = calloc(1, bytes_to_read);
  215. tunnel_te = calloc(1, bytes_to_read);
  216. if (!tunnel_he || !tunnel_te) {
  217. LOG_ERROR("Unable to allocate memory");
  218. free(tunnel_he);
  219. free(tunnel_te);
  220. return ERROR_FAIL;
  221. }
  222. /* We can read only word-aligned words. */
  223. retval = arc_mem_read_block(target, address & ~3u, sizeof(uint32_t),
  224. words_to_read, tunnel_he);
  225. /* arc_..._read_mem with size 4/2 returns uint32_t/uint16_t in host */
  226. /* endianness, but byte array should represent target endianness */
  227. if (retval == ERROR_OK) {
  228. switch (size) {
  229. case 4:
  230. target_buffer_set_u32_array(target, buffer, count,
  231. tunnel_he);
  232. break;
  233. case 2:
  234. target_buffer_set_u32_array(target, tunnel_te,
  235. words_to_read, tunnel_he);
  236. /* Will that work properly with count > 1 and big endian? */
  237. memcpy(buffer, tunnel_te + (address & 3u),
  238. count * sizeof(uint16_t));
  239. break;
  240. case 1:
  241. target_buffer_set_u32_array(target, tunnel_te,
  242. words_to_read, tunnel_he);
  243. /* Will that work properly with count > 1 and big endian? */
  244. memcpy(buffer, tunnel_te + (address & 3u), count);
  245. break;
  246. }
  247. }
  248. free(tunnel_he);
  249. free(tunnel_te);
  250. return retval;
  251. }