1 /***************************************************************************
2 * Copyright (C) 2005 by Dominic Rath *
3 * Dominic.Rath@gmx.de *
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. *
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. *
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 ***************************************************************************/
24 #include "arm7_9_common.h"
27 #include "armv4_5_mmu.h"
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
);
34 char* armv4_5_mmu_page_type_names
[] =
36 "section", "large page", "small page", "tiny page"
39 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
)
41 u32 first_lvl_descriptor
= 0x0;
42 u32 second_lvl_descriptor
= 0x0;
43 u32 ttb
= armv4_5_mmu
->get_ttb(target
);
45 armv4_5_mmu_read_physical(target
, armv4_5_mmu
,
46 (ttb
& 0xffffc000) | ((va
& 0xfff00000) >> 18),
47 4, 1, (u8
*)&first_lvl_descriptor
);
48 first_lvl_descriptor
= target_buffer_get_u32(target
, (u8
*)&first_lvl_descriptor
);
50 LOG_DEBUG("1st lvl desc: %8.8x", first_lvl_descriptor
);
52 if ((first_lvl_descriptor
& 0x3) == 0)
55 LOG_ERROR("Address translation failure");
56 return ERROR_TARGET_TRANSLATION_FAULT
;
59 if (!armv4_5_mmu
->has_tiny_pages
&& ((first_lvl_descriptor
& 0x3) == 3))
62 LOG_ERROR("Address translation failure");
63 return ERROR_TARGET_TRANSLATION_FAULT
;
66 /* domain is always specified in bits 8-5 */
67 *domain
= (first_lvl_descriptor
& 0x1e0) >> 5;
69 if ((first_lvl_descriptor
& 0x3) == 2)
71 /* section descriptor */
72 *type
= ARMV4_5_SECTION
;
73 *cb
= (first_lvl_descriptor
& 0xc) >> 2;
74 *ap
= (first_lvl_descriptor
& 0xc00) >> 10;
75 return (first_lvl_descriptor
& 0xfff00000) | (va
& 0x000fffff);
78 if ((first_lvl_descriptor
& 0x3) == 1)
80 /* coarse page table */
81 armv4_5_mmu_read_physical(target
, armv4_5_mmu
,
82 (first_lvl_descriptor
& 0xfffffc00) | ((va
& 0x000ff000) >> 10),
83 4, 1, (u8
*)&second_lvl_descriptor
);
85 else if ((first_lvl_descriptor
& 0x3) == 3)
88 armv4_5_mmu_read_physical(target
, armv4_5_mmu
,
89 (first_lvl_descriptor
& 0xfffff000) | ((va
& 0x000ffc00) >> 8),
90 4, 1, (u8
*)&second_lvl_descriptor
);
93 second_lvl_descriptor
= target_buffer_get_u32(target
, (u8
*)&second_lvl_descriptor
);
95 LOG_DEBUG("2nd lvl desc: %8.8x", second_lvl_descriptor
);
97 if ((second_lvl_descriptor
& 0x3) == 0)
100 LOG_ERROR("Address translation failure");
101 return ERROR_TARGET_TRANSLATION_FAULT
;
104 /* cacheable/bufferable is always specified in bits 3-2 */
105 *cb
= (second_lvl_descriptor
& 0xc) >> 2;
107 if ((second_lvl_descriptor
& 0x3) == 1)
109 /* large page descriptor */
110 *type
= ARMV4_5_LARGE_PAGE
;
111 *ap
= (second_lvl_descriptor
& 0xff0) >> 4;
112 return (second_lvl_descriptor
& 0xffff0000) | (va
& 0x0000ffff);
115 if ((second_lvl_descriptor
& 0x3) == 2)
117 /* small page descriptor */
118 *type
= ARMV4_5_SMALL_PAGE
;
119 *ap
= (second_lvl_descriptor
& 0xff0) >> 4;
120 return (second_lvl_descriptor
& 0xfffff000) | (va
& 0x00000fff);
123 if ((second_lvl_descriptor
& 0x3) == 3)
125 /* tiny page descriptor */
126 *type
= ARMV4_5_TINY_PAGE
;
127 *ap
= (second_lvl_descriptor
& 0x30) >> 4;
128 return (second_lvl_descriptor
& 0xfffffc00) | (va
& 0x000003ff);
131 /* should not happen */
133 LOG_ERROR("Address translation failure");
134 return ERROR_TARGET_TRANSLATION_FAULT
;
137 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
)
141 if (target
->state
!= TARGET_HALTED
)
142 return ERROR_TARGET_NOT_HALTED
;
144 /* disable MMU and data (or unified) cache */
145 armv4_5_mmu
->disable_mmu_caches(target
, 1, 1, 0);
147 retval
= armv4_5_mmu
->read_memory(target
, address
, size
, count
, buffer
);
149 /* reenable MMU / cache */
150 armv4_5_mmu
->enable_mmu_caches(target
, armv4_5_mmu
->mmu_enabled
,
151 armv4_5_mmu
->armv4_5_cache
.d_u_cache_enabled
,
152 armv4_5_mmu
->armv4_5_cache
.i_cache_enabled
);
157 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
)
161 if (target
->state
!= TARGET_HALTED
)
162 return ERROR_TARGET_NOT_HALTED
;
164 /* disable MMU and data (or unified) cache */
165 armv4_5_mmu
->disable_mmu_caches(target
, 1, 1, 0);
167 retval
= armv4_5_mmu
->write_memory(target
, address
, size
, count
, buffer
);
169 /* reenable MMU / cache */
170 armv4_5_mmu
->enable_mmu_caches(target
, armv4_5_mmu
->mmu_enabled
,
171 armv4_5_mmu
->armv4_5_cache
.d_u_cache_enabled
,
172 armv4_5_mmu
->armv4_5_cache
.i_cache_enabled
);
177 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
)
186 if (target
->state
!= TARGET_HALTED
)
188 command_print(cmd_ctx
, "target must be stopped for \"virt2phys\" command");
194 command_print(cmd_ctx
, "usage: virt2phys <virtual address>");
200 va
= strtoul(args
[0], NULL
, 0);
201 pa
= armv4_5_mmu_translate_va(target
, armv4_5_mmu
, va
, &type
, &cb
, &domain
, &ap
);
206 case ERROR_TARGET_TRANSLATION_FAULT
:
207 command_print(cmd_ctx
, "no valid translation for 0x%8.8x", va
);
210 command_print(cmd_ctx
, "unknown translation error");
215 command_print(cmd_ctx
, "0x%8.8x -> 0x%8.8x, type: %s, cb: %i, domain: %i, ap: %2.2x",
216 va
, pa
, armv4_5_mmu_page_type_names
[type
], cb
, domain
, ap
);
222 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
)
236 if (target
->state
!= TARGET_HALTED
)
238 command_print(cmd_ctx
, "target must be stopped for \"%s\" command", cmd
);
246 count
= strtoul(args
[1], NULL
, 0);
248 address
= strtoul(args
[0], NULL
, 0);
265 buffer
= calloc(count
, size
);
266 if ((retval
= armv4_5_mmu_read_physical(target
, armv4_5_mmu
, address
, size
, count
, buffer
)) != ERROR_OK
)
270 case ERROR_TARGET_UNALIGNED_ACCESS
:
271 command_print(cmd_ctx
, "error: address not aligned");
273 case ERROR_TARGET_NOT_HALTED
:
274 command_print(cmd_ctx
, "error: target must be halted for memory accesses");
276 case ERROR_TARGET_DATA_ABORT
:
277 command_print(cmd_ctx
, "error: access caused data abort, system possibly corrupted");
280 command_print(cmd_ctx
, "error: unknown error");
286 for (i
= 0; i
< count
; i
++)
289 output_len
+= snprintf(output
+ output_len
, 128 - output_len
, "0x%8.8x: ", address
+ (i
*size
));
294 output_len
+= snprintf(output
+ output_len
, 128 - output_len
, "%8.8x ", target_buffer_get_u32(target
, &buffer
[i
*4]));
297 output_len
+= snprintf(output
+ output_len
, 128 - output_len
, "%4.4x ", target_buffer_get_u16(target
, &buffer
[i
*2]));
300 output_len
+= snprintf(output
+ output_len
, 128 - output_len
, "%2.2x ", buffer
[i
*1]);
304 if ((i
% 8 == 7) || (i
== count
- 1))
306 command_print(cmd_ctx
, output
);
316 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
)
323 if (target
->state
!= TARGET_HALTED
)
325 command_print(cmd_ctx
, "target must be stopped for \"%s\" command", cmd
);
332 address
= strtoul(args
[0], NULL
, 0);
333 value
= strtoul(args
[1], NULL
, 0);
338 target_buffer_set_u32(target
, value_buf
, value
);
339 retval
= armv4_5_mmu_write_physical(target
, armv4_5_mmu
, address
, 4, 1, value_buf
);
342 target_buffer_set_u16(target
, value_buf
, value
);
343 retval
= armv4_5_mmu_write_physical(target
, armv4_5_mmu
, address
, 2, 1, value_buf
);
346 value_buf
[0] = value
;
347 retval
= armv4_5_mmu_write_physical(target
, armv4_5_mmu
, address
, 1, 1, value_buf
);
355 case ERROR_TARGET_UNALIGNED_ACCESS
:
356 command_print(cmd_ctx
, "error: address not aligned");
358 case ERROR_TARGET_DATA_ABORT
:
359 command_print(cmd_ctx
, "error: access caused data abort, system possibly corrupted");
361 case ERROR_TARGET_NOT_HALTED
:
362 command_print(cmd_ctx
, "error: target must be halted for memory accesses");
367 command_print(cmd_ctx
, "error: unknown error");
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)