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

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)