file not found SEGFAULT fix
[openocd.git] / src / target / armv4_5_mmu.c
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
24 #include "arm7_9_common.h"
25 #include "log.h"
26 #include "command.h"
27 #include "armv4_5_mmu.h"
28 #include "target.h"
29
30 #include <stdlib.h>
31
32 u32 armv4mmu_translate_va(target_t *target, armv4_5_mmu_common_t *armv4_5_mmu, u32 va, int *type, u32 *cb, int *domain, u32 *ap);
33 int armv4_5_mmu_read_physical(target_t *target, armv4_5_mmu_common_t *armv4_5_mmu, u32 address, u32 size, u32 count, u8 *buffer);
34 int armv4_5_mmu_write_physical(target_t *target, armv4_5_mmu_common_t *armv4_5_mmu, u32 address, u32 size, u32 count, u8 *buffer);
35
36 char* armv4_5_mmu_page_type_names[] =
37 {
38 "section", "large page", "small page", "tiny page"
39 };
40
41 u32 armv4_5_mmu_translate_va(target_t *target, armv4_5_mmu_common_t *armv4_5_mmu, u32 va, int *type, u32 *cb, int *domain, u32 *ap)
42 {
43 u32 first_lvl_descriptor = 0x0;
44 u32 second_lvl_descriptor = 0x0;
45 u32 ttb = armv4_5_mmu->get_ttb(target);
46
47 armv4_5_mmu_read_physical(target, armv4_5_mmu,
48 (ttb & 0xffffc000) | ((va & 0xfff00000) >> 18),
49 4, 1, (u8*)&first_lvl_descriptor);
50 first_lvl_descriptor = target_buffer_get_u32(target, (u8*)&first_lvl_descriptor);
51
52 LOG_DEBUG("1st lvl desc: %8.8x", first_lvl_descriptor);
53
54 if ((first_lvl_descriptor & 0x3) == 0)
55 {
56 *type = -1;
57 LOG_ERROR("Address translation failure");
58 return ERROR_TARGET_TRANSLATION_FAULT;
59 }
60
61 if (!armv4_5_mmu->has_tiny_pages && ((first_lvl_descriptor & 0x3) == 3))
62 {
63 *type = -1;
64 LOG_ERROR("Address translation failure");
65 return ERROR_TARGET_TRANSLATION_FAULT;
66 }
67
68 /* domain is always specified in bits 8-5 */
69 *domain = (first_lvl_descriptor & 0x1e0) >> 5;
70
71 if ((first_lvl_descriptor & 0x3) == 2)
72 {
73 /* section descriptor */
74 *type = ARMV4_5_SECTION;
75 *cb = (first_lvl_descriptor & 0xc) >> 2;
76 *ap = (first_lvl_descriptor & 0xc00) >> 10;
77 return (first_lvl_descriptor & 0xfff00000) | (va & 0x000fffff);
78 }
79
80 if ((first_lvl_descriptor & 0x3) == 1)
81 {
82 /* coarse page table */
83 armv4_5_mmu_read_physical(target, armv4_5_mmu,
84 (first_lvl_descriptor & 0xfffffc00) | ((va & 0x000ff000) >> 10),
85 4, 1, (u8*)&second_lvl_descriptor);
86 }
87 else if ((first_lvl_descriptor & 0x3) == 3)
88 {
89 /* fine page table */
90 armv4_5_mmu_read_physical(target, armv4_5_mmu,
91 (first_lvl_descriptor & 0xfffff000) | ((va & 0x000ffc00) >> 8),
92 4, 1, (u8*)&second_lvl_descriptor);
93 }
94
95 second_lvl_descriptor = target_buffer_get_u32(target, (u8*)&second_lvl_descriptor);
96
97 LOG_DEBUG("2nd lvl desc: %8.8x", second_lvl_descriptor);
98
99 if ((second_lvl_descriptor & 0x3) == 0)
100 {
101 *type = -1;
102 LOG_ERROR("Address translation failure");
103 return ERROR_TARGET_TRANSLATION_FAULT;
104 }
105
106 /* cacheable/bufferable is always specified in bits 3-2 */
107 *cb = (second_lvl_descriptor & 0xc) >> 2;
108
109 if ((second_lvl_descriptor & 0x3) == 1)
110 {
111 /* large page descriptor */
112 *type = ARMV4_5_LARGE_PAGE;
113 *ap = (second_lvl_descriptor & 0xff0) >> 4;
114 return (second_lvl_descriptor & 0xffff0000) | (va & 0x0000ffff);
115 }
116
117 if ((second_lvl_descriptor & 0x3) == 2)
118 {
119 /* small page descriptor */
120 *type = ARMV4_5_SMALL_PAGE;
121 *ap = (second_lvl_descriptor & 0xff0) >> 4;
122 return (second_lvl_descriptor & 0xfffff000) | (va & 0x00000fff);
123 }
124
125 if ((second_lvl_descriptor & 0x3) == 3)
126 {
127 /* tiny page descriptor */
128 *type = ARMV4_5_TINY_PAGE;
129 *ap = (second_lvl_descriptor & 0x30) >> 4;
130 return (second_lvl_descriptor & 0xfffffc00) | (va & 0x000003ff);
131 }
132
133 /* should not happen */
134 *type = -1;
135 LOG_ERROR("Address translation failure");
136 return ERROR_TARGET_TRANSLATION_FAULT;
137 }
138
139 int armv4_5_mmu_read_physical(target_t *target, armv4_5_mmu_common_t *armv4_5_mmu, u32 address, u32 size, u32 count, u8 *buffer)
140 {
141 int retval;
142
143 if (target->state != TARGET_HALTED)
144 return ERROR_TARGET_NOT_HALTED;
145
146 /* disable MMU and data (or unified) cache */
147 armv4_5_mmu->disable_mmu_caches(target, 1, 1, 0);
148
149 retval = armv4_5_mmu->read_memory(target, address, size, count, buffer);
150
151 /* reenable MMU / cache */
152 armv4_5_mmu->enable_mmu_caches(target, armv4_5_mmu->mmu_enabled,
153 armv4_5_mmu->armv4_5_cache.d_u_cache_enabled,
154 armv4_5_mmu->armv4_5_cache.i_cache_enabled);
155
156 return retval;
157 }
158
159 int armv4_5_mmu_write_physical(target_t *target, armv4_5_mmu_common_t *armv4_5_mmu, u32 address, u32 size, u32 count, u8 *buffer)
160 {
161 int retval;
162
163 if (target->state != TARGET_HALTED)
164 return ERROR_TARGET_NOT_HALTED;
165
166 /* disable MMU and data (or unified) cache */
167 armv4_5_mmu->disable_mmu_caches(target, 1, 1, 0);
168
169 retval = armv4_5_mmu->write_memory(target, address, size, count, buffer);
170
171 /* reenable MMU / cache */
172 armv4_5_mmu->enable_mmu_caches(target, armv4_5_mmu->mmu_enabled,
173 armv4_5_mmu->armv4_5_cache.d_u_cache_enabled,
174 armv4_5_mmu->armv4_5_cache.i_cache_enabled);
175
176 return retval;
177 }
178
179 int armv4_5_mmu_handle_virt2phys_command(command_context_t *cmd_ctx, char *cmd, char **args, int argc, target_t *target, armv4_5_mmu_common_t *armv4_5_mmu)
180 {
181 u32 va;
182 u32 pa;
183 int type;
184 u32 cb;
185 int domain;
186 u32 ap;
187
188 if (target->state != TARGET_HALTED)
189 {
190 command_print(cmd_ctx, "target must be stopped for \"virt2phys\" command");
191 return ERROR_OK;
192 }
193
194 if (argc == 0)
195 {
196 command_print(cmd_ctx, "usage: virt2phys <virtual address>");
197 return ERROR_OK;
198 }
199
200 if (argc == 1)
201 {
202 va = strtoul(args[0], NULL, 0);
203 pa = armv4_5_mmu_translate_va(target, armv4_5_mmu, va, &type, &cb, &domain, &ap);
204 if (type == -1)
205 {
206 switch (pa)
207 {
208 case ERROR_TARGET_TRANSLATION_FAULT:
209 command_print(cmd_ctx, "no valid translation for 0x%8.8x", va);
210 break;
211 default:
212 command_print(cmd_ctx, "unknown translation error");
213 }
214 return ERROR_OK;
215 }
216
217 command_print(cmd_ctx, "0x%8.8x -> 0x%8.8x, type: %s, cb: %i, domain: %i, ap: %2.2x",
218 va, pa, armv4_5_mmu_page_type_names[type], cb, domain, ap);
219 }
220
221 return ERROR_OK;
222 }
223
224 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)
225 {
226 int count = 1;
227 int size = 4;
228 u32 address = 0;
229 int i;
230
231 char output[128];
232 int output_len;
233
234 int retval;
235
236 u8 *buffer;
237
238 if (target->state != TARGET_HALTED)
239 {
240 command_print(cmd_ctx, "target must be stopped for \"%s\" command", cmd);
241 return ERROR_OK;
242 }
243
244 if (argc < 1)
245 return ERROR_OK;
246
247 if (argc == 2)
248 count = strtoul(args[1], NULL, 0);
249
250 address = strtoul(args[0], NULL, 0);
251
252 switch (cmd[2])
253 {
254 case 'w':
255 size = 4;
256 break;
257 case 'h':
258 size = 2;
259 break;
260 case 'b':
261 size = 1;
262 break;
263 default:
264 return ERROR_OK;
265 }
266
267 buffer = calloc(count, size);
268 if ((retval = armv4_5_mmu_read_physical(target, armv4_5_mmu, address, size, count, buffer)) != ERROR_OK)
269 {
270 switch (retval)
271 {
272 case ERROR_TARGET_UNALIGNED_ACCESS:
273 command_print(cmd_ctx, "error: address not aligned");
274 break;
275 case ERROR_TARGET_NOT_HALTED:
276 command_print(cmd_ctx, "error: target must be halted for memory accesses");
277 break;
278 case ERROR_TARGET_DATA_ABORT:
279 command_print(cmd_ctx, "error: access caused data abort, system possibly corrupted");
280 break;
281 default:
282 command_print(cmd_ctx, "error: unknown error");
283 }
284 }
285
286 output_len = 0;
287
288 for (i = 0; i < count; i++)
289 {
290 if (i%8 == 0)
291 output_len += snprintf(output + output_len, 128 - output_len, "0x%8.8x: ", address + (i*size));
292
293 switch (size)
294 {
295 case 4:
296 output_len += snprintf(output + output_len, 128 - output_len, "%8.8x ", target_buffer_get_u32(target, &buffer[i*4]));
297 break;
298 case 2:
299 output_len += snprintf(output + output_len, 128 - output_len, "%4.4x ", target_buffer_get_u16(target, &buffer[i*2]));
300 break;
301 case 1:
302 output_len += snprintf(output + output_len, 128 - output_len, "%2.2x ", buffer[i*1]);
303 break;
304 }
305
306 if ((i % 8 == 7) || (i == count - 1))
307 {
308 command_print(cmd_ctx, output);
309 output_len = 0;
310 }
311 }
312
313 free(buffer);
314
315 return ERROR_OK;
316 }
317
318 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)
319 {
320 u32 address = 0;
321 u32 value = 0;
322 int retval;
323 u8 value_buf[4];
324
325 if (target->state != TARGET_HALTED)
326 {
327 command_print(cmd_ctx, "target must be stopped for \"%s\" command", cmd);
328 return ERROR_OK;
329 }
330
331 if (argc < 2)
332 return ERROR_OK;
333
334 address = strtoul(args[0], NULL, 0);
335 value = strtoul(args[1], NULL, 0);
336
337 switch (cmd[2])
338 {
339 case 'w':
340 target_buffer_set_u32(target, value_buf, value);
341 retval = armv4_5_mmu_write_physical(target, armv4_5_mmu, address, 4, 1, value_buf);
342 break;
343 case 'h':
344 target_buffer_set_u16(target, value_buf, value);
345 retval = armv4_5_mmu_write_physical(target, armv4_5_mmu, address, 2, 1, value_buf);
346 break;
347 case 'b':
348 value_buf[0] = value;
349 retval = armv4_5_mmu_write_physical(target, armv4_5_mmu, address, 1, 1, value_buf);
350 break;
351 default:
352 return ERROR_OK;
353 }
354
355 switch (retval)
356 {
357 case ERROR_TARGET_UNALIGNED_ACCESS:
358 command_print(cmd_ctx, "error: address not aligned");
359 break;
360 case ERROR_TARGET_DATA_ABORT:
361 command_print(cmd_ctx, "error: access caused data abort, system possibly corrupted");
362 break;
363 case ERROR_TARGET_NOT_HALTED:
364 command_print(cmd_ctx, "error: target must be halted for memory accesses");
365 break;
366 case ERROR_OK:
367 break;
368 default:
369 command_print(cmd_ctx, "error: unknown error");
370 }
371
372 return ERROR_OK;
373 }

Linking to existing account procedure

If you already have an account and want to add another login method you MUST first sign in with your existing account and then change URL to read https://review.openocd.org/login/?link to get to this page again but this time it'll work for linking. Thank you.

SSH host keys fingerprints

1024 SHA256:YKx8b7u5ZWdcbp7/4AeXNaqElP49m6QrwfXaqQGJAOk gerrit-code-review@openocd.zylin.com (DSA)
384 SHA256:jHIbSQa4REvwCFG4cq5LBlBLxmxSqelQPem/EXIrxjk gerrit-code-review@openocd.org (ECDSA)
521 SHA256:UAOPYkU9Fjtcao0Ul/Rrlnj/OsQvt+pgdYSZ4jOYdgs gerrit-code-review@openocd.org (ECDSA)
256 SHA256:A13M5QlnozFOvTllybRZH6vm7iSt0XLxbA48yfc2yfY gerrit-code-review@openocd.org (ECDSA)
256 SHA256:spYMBqEYoAOtK7yZBrcwE8ZpYt6b68Cfh9yEVetvbXg gerrit-code-review@openocd.org (ED25519)
+--[ED25519 256]--+
|=..              |
|+o..   .         |
|*.o   . .        |
|+B . . .         |
|Bo. = o S        |
|Oo.+ + =         |
|oB=.* = . o      |
| =+=.+   + E     |
|. .=o   . o      |
+----[SHA256]-----+
2048 SHA256:0Onrb7/PHjpo6iVZ7xQX2riKN83FJ3KGU0TvI0TaFG4 gerrit-code-review@openocd.zylin.com (RSA)