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
);
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
);
36 char* armv4_5_mmu_page_type_names
[] =
38 "section", "large page", "small page", "tiny page"
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
)
43 u32 first_lvl_descriptor
= 0x0;
44 u32 second_lvl_descriptor
= 0x0;
45 u32 ttb
= armv4_5_mmu
->get_ttb(target
);
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
);
52 DEBUG("1st lvl desc: %8.8x", first_lvl_descriptor
);
54 if ((first_lvl_descriptor
& 0x3) == 0)
57 return ERROR_TARGET_TRANSLATION_FAULT
;
60 if (!armv4_5_mmu
->has_tiny_pages
&& ((first_lvl_descriptor
& 0x3) == 3))
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 DEBUG("2nd lvl desc: %8.8x", second_lvl_descriptor
);
97 if ((second_lvl_descriptor
& 0x3) == 0)
100 return ERROR_TARGET_TRANSLATION_FAULT
;
103 /* cacheable/bufferable is always specified in bits 3-2 */
104 *cb
= (second_lvl_descriptor
& 0xc) >> 2;
106 if ((second_lvl_descriptor
& 0x3) == 1)
108 /* large page descriptor */
109 *type
= ARMV4_5_LARGE_PAGE
;
110 *ap
= (second_lvl_descriptor
& 0xff0) >> 4;
111 return (second_lvl_descriptor
& 0xffff0000) | (va
& 0x0000ffff);
114 if ((second_lvl_descriptor
& 0x3) == 2)
116 /* small page descriptor */
117 *type
= ARMV4_5_SMALL_PAGE
;
118 *ap
= (second_lvl_descriptor
& 0xff0) >> 4;
119 return (second_lvl_descriptor
& 0xfffff000) | (va
& 0x00000fff);
122 if ((second_lvl_descriptor
& 0x3) == 3)
124 /* tiny page descriptor */
125 *type
= ARMV4_5_TINY_PAGE
;
126 *ap
= (second_lvl_descriptor
& 0x30) >> 4;
127 return (second_lvl_descriptor
& 0xfffffc00) | (va
& 0x000003ff);
130 /* should not happen */
132 return ERROR_TARGET_TRANSLATION_FAULT
;
135 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
)
139 if (target
->state
!= TARGET_HALTED
)
140 return ERROR_TARGET_NOT_HALTED
;
142 /* disable MMU and data (or unified) cache */
143 armv4_5_mmu
->disable_mmu_caches(target
, 1, 1, 0);
145 retval
= armv4_5_mmu
->read_memory(target
, address
, size
, count
, buffer
);
147 /* reenable MMU / cache */
148 armv4_5_mmu
->enable_mmu_caches(target
, armv4_5_mmu
->mmu_enabled
,
149 armv4_5_mmu
->armv4_5_cache
.d_u_cache_enabled
,
150 armv4_5_mmu
->armv4_5_cache
.i_cache_enabled
);
155 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
)
159 if (target
->state
!= TARGET_HALTED
)
160 return ERROR_TARGET_NOT_HALTED
;
162 /* disable MMU and data (or unified) cache */
163 armv4_5_mmu
->disable_mmu_caches(target
, 1, 1, 0);
165 retval
= armv4_5_mmu
->write_memory(target
, address
, size
, count
, buffer
);
167 /* reenable MMU / cache */
168 armv4_5_mmu
->enable_mmu_caches(target
, armv4_5_mmu
->mmu_enabled
,
169 armv4_5_mmu
->armv4_5_cache
.d_u_cache_enabled
,
170 armv4_5_mmu
->armv4_5_cache
.i_cache_enabled
);
175 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
)
184 if (target
->state
!= TARGET_HALTED
)
186 command_print(cmd_ctx
, "target must be stopped for \"virt2phys\" command");
192 command_print(cmd_ctx
, "usage: virt2phys <virtual address>");
198 va
= strtoul(args
[0], NULL
, 0);
199 pa
= armv4_5_mmu_translate_va(target
, armv4_5_mmu
, va
, &type
, &cb
, &domain
, &ap
);
204 case ERROR_TARGET_TRANSLATION_FAULT
:
205 command_print(cmd_ctx
, "no valid translation for 0x%8.8x", va
);
208 command_print(cmd_ctx
, "unknown translation error");
213 command_print(cmd_ctx
, "0x%8.8x -> 0x%8.8x, type: %s, cb: %i, domain: %i, ap: %2.2x",
214 va
, pa
, armv4_5_mmu_page_type_names
[type
], cb
, domain
, ap
);
220 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
)
234 if (target
->state
!= TARGET_HALTED
)
236 command_print(cmd_ctx
, "target must be stopped for \"%s\" command", cmd
);
244 count
= strtoul(args
[1], NULL
, 0);
246 address
= strtoul(args
[0], NULL
, 0);
263 buffer
= calloc(count
, size
);
264 if ((retval
= armv4_5_mmu_read_physical(target
, armv4_5_mmu
, address
, size
, count
, buffer
)) != ERROR_OK
)
268 case ERROR_TARGET_UNALIGNED_ACCESS
:
269 command_print(cmd_ctx
, "error: address not aligned");
271 case ERROR_TARGET_NOT_HALTED
:
272 command_print(cmd_ctx
, "error: target must be halted for memory accesses");
274 case ERROR_TARGET_DATA_ABORT
:
275 command_print(cmd_ctx
, "error: access caused data abort, system possibly corrupted");
278 command_print(cmd_ctx
, "error: unknown error");
284 for (i
= 0; i
< count
; i
++)
287 output_len
+= snprintf(output
+ output_len
, 128 - output_len
, "0x%8.8x: ", address
+ (i
*size
));
292 output_len
+= snprintf(output
+ output_len
, 128 - output_len
, "%8.8x ", target_buffer_get_u32(target
, &buffer
[i
*4]));
295 output_len
+= snprintf(output
+ output_len
, 128 - output_len
, "%4.4x ", target_buffer_get_u16(target
, &buffer
[i
*2]));
298 output_len
+= snprintf(output
+ output_len
, 128 - output_len
, "%2.2x ", buffer
[i
*1]);
302 if ((i
% 8 == 7) || (i
== count
- 1))
304 command_print(cmd_ctx
, output
);
314 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
)
321 if (target
->state
!= TARGET_HALTED
)
323 command_print(cmd_ctx
, "target must be stopped for \"%s\" command", cmd
);
330 address
= strtoul(args
[0], NULL
, 0);
331 value
= strtoul(args
[1], NULL
, 0);
336 target_buffer_set_u32(target
, value_buf
, value
);
337 retval
= armv4_5_mmu_write_physical(target
, armv4_5_mmu
, address
, 4, 1, value_buf
);
340 target_buffer_set_u16(target
, value_buf
, value
);
341 retval
= armv4_5_mmu_write_physical(target
, armv4_5_mmu
, address
, 2, 1, value_buf
);
344 value_buf
[0] = value
;
345 retval
= armv4_5_mmu_write_physical(target
, armv4_5_mmu
, address
, 1, 1, value_buf
);
353 case ERROR_TARGET_UNALIGNED_ACCESS
:
354 command_print(cmd_ctx
, "error: address not aligned");
356 case ERROR_TARGET_DATA_ABORT
:
357 command_print(cmd_ctx
, "error: access caused data abort, system possibly corrupted");
359 case ERROR_TARGET_NOT_HALTED
:
360 command_print(cmd_ctx
, "error: target must be halted for memory accesses");
365 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)