command_handler: change 'cmd_ctx' to CMD_CTX
[openocd.git] / src / target / armv7a.c
1 /***************************************************************************
2 * Copyright (C) 2009 by David Brownell *
3 * *
4 * This program is free software; you can redistribute it and/or modify *
5 * it under the terms of the GNU General Public License as published by *
6 * the Free Software Foundation; either version 2 of the License, or *
7 * (at your option) any later version. *
8 * *
9 * This program is distributed in the hope that it will be useful, *
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
12 * GNU General Public License for more details. *
13 * *
14 * You should have received a copy of the GNU General Public License *
15 * along with this program; if not, write to the *
16 * Free Software Foundation, Inc., *
17 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
18 ***************************************************************************/
19 #ifdef HAVE_CONFIG_H
20 #include "config.h"
21 #endif
22
23 #include "replacements.h"
24
25 #include "armv7a.h"
26 #include "arm_disassembler.h"
27
28 #include "register.h"
29 #include "binarybuffer.h"
30 #include "command.h"
31
32 #include <stdlib.h>
33 #include <string.h>
34 #include <unistd.h>
35
36
37 char* armv7a_core_reg_list[] =
38 {
39 "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
40 "r8", "r9", "r10", "r11", "r12", "r13_usr", "lr_usr", "pc",
41 "r8_fiq", "r9_fiq", "r10_fiq", "r11_fiq", "r12_fiq", "r13_fiq", "lr_fiq",
42 "r13_irq", "lr_irq",
43 "r13_svc", "lr_svc",
44 "r13_abt", "lr_abt",
45 "r13_und", "lr_und",
46 "cpsr", "spsr_fiq", "spsr_irq", "spsr_svc", "spsr_abt", "spsr_und",
47 "r13_mon", "lr_mon", "spsr_mon"
48 };
49
50 char * armv7a_mode_strings_list[] =
51 {
52 "Illegal mode value", "User", "FIQ", "IRQ",
53 "Supervisor", "Abort", "Undefined", "System", "Monitor"
54 };
55
56 /* Hack! Yuk! allow -1 index, which simplifies codepaths elsewhere in the code */
57 char** armv7a_mode_strings = armv7a_mode_strings_list+1;
58
59 char* armv7a_state_strings[] =
60 {
61 "ARM", "Thumb", "Jazelle", "ThumbEE"
62 };
63
64 struct armv7a_core_reg armv7a_core_reg_list_arch_info[] =
65 {
66 {0, ARMV4_5_MODE_ANY, NULL, NULL},
67 {1, ARMV4_5_MODE_ANY, NULL, NULL},
68 {2, ARMV4_5_MODE_ANY, NULL, NULL},
69 {3, ARMV4_5_MODE_ANY, NULL, NULL},
70 {4, ARMV4_5_MODE_ANY, NULL, NULL},
71 {5, ARMV4_5_MODE_ANY, NULL, NULL},
72 {6, ARMV4_5_MODE_ANY, NULL, NULL},
73 {7, ARMV4_5_MODE_ANY, NULL, NULL},
74 {8, ARMV4_5_MODE_ANY, NULL, NULL},
75 {9, ARMV4_5_MODE_ANY, NULL, NULL},
76 {10, ARMV4_5_MODE_ANY, NULL, NULL},
77 {11, ARMV4_5_MODE_ANY, NULL, NULL},
78 {12, ARMV4_5_MODE_ANY, NULL, NULL},
79 {13, ARMV4_5_MODE_USR, NULL, NULL},
80 {14, ARMV4_5_MODE_USR, NULL, NULL},
81 {15, ARMV4_5_MODE_ANY, NULL, NULL},
82
83 {8, ARMV4_5_MODE_FIQ, NULL, NULL},
84 {9, ARMV4_5_MODE_FIQ, NULL, NULL},
85 {10, ARMV4_5_MODE_FIQ, NULL, NULL},
86 {11, ARMV4_5_MODE_FIQ, NULL, NULL},
87 {12, ARMV4_5_MODE_FIQ, NULL, NULL},
88 {13, ARMV4_5_MODE_FIQ, NULL, NULL},
89 {14, ARMV4_5_MODE_FIQ, NULL, NULL},
90
91 {13, ARMV4_5_MODE_IRQ, NULL, NULL},
92 {14, ARMV4_5_MODE_IRQ, NULL, NULL},
93
94 {13, ARMV4_5_MODE_SVC, NULL, NULL},
95 {14, ARMV4_5_MODE_SVC, NULL, NULL},
96
97 {13, ARMV4_5_MODE_ABT, NULL, NULL},
98 {14, ARMV4_5_MODE_ABT, NULL, NULL},
99
100 {13, ARMV4_5_MODE_UND, NULL, NULL},
101 {14, ARMV4_5_MODE_UND, NULL, NULL},
102
103 {16, ARMV4_5_MODE_ANY, NULL, NULL},
104 {16, ARMV4_5_MODE_FIQ, NULL, NULL},
105 {16, ARMV4_5_MODE_IRQ, NULL, NULL},
106 {16, ARMV4_5_MODE_SVC, NULL, NULL},
107 {16, ARMV4_5_MODE_ABT, NULL, NULL},
108 {16, ARMV4_5_MODE_UND, NULL, NULL},
109
110 {13, ARMV7A_MODE_MON, NULL, NULL},
111 {14, ARMV7A_MODE_MON, NULL, NULL},
112 {16, ARMV7A_MODE_MON, NULL, NULL}
113 };
114
115 /* map core mode (USR, FIQ, ...) and register number to indizes into the register cache */
116 int armv7a_core_reg_map[8][17] =
117 {
118 { /* USR */
119 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 31
120 },
121 { /* FIQ */
122 0, 1, 2, 3, 4, 5, 6, 7, 16, 17, 18, 19, 20, 21, 22, 15, 32
123 },
124 { /* IRQ */
125 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 23, 24, 15, 33
126 },
127 { /* SVC */
128 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 25, 26, 15, 34
129 },
130 { /* ABT */
131 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 27, 28, 15, 35
132 },
133 { /* UND */
134 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 29, 30, 15, 36
135 },
136 { /* SYS */
137 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 31
138 },
139 { /* MON */
140 /* TODO Fix the register mapping for mon, we need r13_mon,
141 * r14_mon and spsr_mon
142 */
143 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 31
144 }
145 };
146
147 /* FIXME this dummy is IDENTICAL to the armv4_5, arm11, and armv7m
148 * ones... except for naming/scoping
149 */
150 uint8_t armv7a_gdb_dummy_fp_value[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
151
152 struct reg armv7a_gdb_dummy_fp_reg =
153 {
154 .name = "GDB dummy floating-point register",
155 .value = armv7a_gdb_dummy_fp_value,
156 .dirty = 0,
157 .valid = 1,
158 .size = 96,
159 .arch_info = NULL,
160 };
161
162 void armv7a_show_fault_registers(struct target *target)
163 {
164 uint32_t dfsr, ifsr, dfar, ifar;
165 struct armv7a_common *armv7a = target_to_armv7a(target);
166
167 armv7a->read_cp15(target, 0, 0, 5, 0, &dfsr);
168 armv7a->read_cp15(target, 0, 1, 5, 0, &ifsr);
169 armv7a->read_cp15(target, 0, 0, 6, 0, &dfar);
170 armv7a->read_cp15(target, 0, 2, 6, 0, &ifar);
171
172 LOG_USER("Data fault registers DFSR: %8.8" PRIx32
173 ", DFAR: %8.8" PRIx32, dfsr, dfar);
174 LOG_USER("Instruction fault registers IFSR: %8.8" PRIx32
175 ", IFAR: %8.8" PRIx32, ifsr, ifar);
176
177 }
178
179 int armv7a_arch_state(struct target *target)
180 {
181 static const char *state[] =
182 {
183 "disabled", "enabled"
184 };
185
186 struct armv7a_common *armv7a = target_to_armv7a(target);
187 struct armv4_5_common_s *armv4_5 = &armv7a->armv4_5_common;
188
189 if (armv7a->common_magic != ARMV7_COMMON_MAGIC)
190 {
191 LOG_ERROR("BUG: called for a non-ARMv7A target");
192 return ERROR_INVALID_ARGUMENTS;
193 }
194
195 LOG_USER("target halted in %s state due to %s, current mode: %s\n"
196 "%s: 0x%8.8" PRIx32 " pc: 0x%8.8" PRIx32 "\n"
197 "MMU: %s, D-Cache: %s, I-Cache: %s",
198 armv7a_state_strings[armv7a->core_state],
199 Jim_Nvp_value2name_simple(nvp_target_debug_reason,
200 target->debug_reason)->name,
201 armv7a_mode_strings[
202 armv7a_mode_to_number(armv4_5->core_mode)],
203 armv7a_core_reg_list[armv7a_core_reg_map[
204 armv7a_mode_to_number(armv4_5->core_mode)][16]],
205 buf_get_u32(ARMV7A_CORE_REG_MODE(armv4_5->core_cache,
206 armv4_5->core_mode, 16).value, 0, 32),
207 buf_get_u32(armv4_5->core_cache->reg_list[15].value, 0, 32),
208 state[armv7a->armv4_5_mmu.mmu_enabled],
209 state[armv7a->armv4_5_mmu.armv4_5_cache.d_u_cache_enabled],
210 state[armv7a->armv4_5_mmu.armv4_5_cache.i_cache_enabled]);
211
212 if (armv4_5->core_mode == ARMV7A_MODE_ABT)
213 armv7a_show_fault_registers(target);
214
215 return ERROR_OK;
216 }
217
218
219 COMMAND_HANDLER(handle_dap_baseaddr_command)
220 {
221 struct target *target = get_current_target(CMD_CTX);
222 struct armv7a_common *armv7a = target_to_armv7a(target);
223 struct swjdp_common *swjdp = &armv7a->swjdp_info;
224
225 return CALL_COMMAND_HANDLER(dap_baseaddr_command, swjdp);
226 }
227
228 COMMAND_HANDLER(handle_dap_memaccess_command)
229 {
230 struct target *target = get_current_target(CMD_CTX);
231 struct armv7a_common *armv7a = target_to_armv7a(target);
232 struct swjdp_common *swjdp = &armv7a->swjdp_info;
233
234 return CALL_COMMAND_HANDLER(dap_memaccess_command, swjdp);
235 }
236
237 COMMAND_HANDLER(handle_dap_apsel_command)
238 {
239 struct target *target = get_current_target(CMD_CTX);
240 struct armv7a_common *armv7a = target_to_armv7a(target);
241 struct swjdp_common *swjdp = &armv7a->swjdp_info;
242
243 return CALL_COMMAND_HANDLER(dap_apsel_command, swjdp);
244 }
245
246 COMMAND_HANDLER(handle_dap_apid_command)
247 {
248 struct target *target = get_current_target(CMD_CTX);
249 struct armv7a_common *armv7a = target_to_armv7a(target);
250 struct swjdp_common *swjdp = &armv7a->swjdp_info;
251
252 return CALL_COMMAND_HANDLER(dap_apid_command, swjdp);
253 }
254
255 COMMAND_HANDLER(handle_dap_info_command)
256 {
257 struct target *target = get_current_target(CMD_CTX);
258 struct armv7a_common *armv7a = target_to_armv7a(target);
259 struct swjdp_common *swjdp = &armv7a->swjdp_info;
260 uint32_t apsel;
261
262 switch (CMD_ARGC) {
263 case 0:
264 apsel = swjdp->apsel;
265 break;
266 case 1:
267 COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], apsel);
268 break;
269 default:
270 return ERROR_COMMAND_SYNTAX_ERROR;
271 }
272
273 return dap_info_command(CMD_CTX, swjdp, apsel);
274 }
275
276 int armv7a_register_commands(struct command_context *cmd_ctx)
277 {
278 struct command *arm_adi_v5_dap_cmd;
279
280 arm_adi_v5_dap_cmd = register_command(cmd_ctx, NULL, "dap",
281 NULL, COMMAND_ANY,
282 "cortex dap specific commands");
283
284 register_command(cmd_ctx, arm_adi_v5_dap_cmd, "info",
285 handle_dap_info_command, COMMAND_EXEC,
286 "dap info for ap [num], "
287 "default currently selected AP");
288 register_command(cmd_ctx, arm_adi_v5_dap_cmd, "apsel",
289 handle_dap_apsel_command, COMMAND_EXEC,
290 "select a different AP [num] (default 0)");
291 register_command(cmd_ctx, arm_adi_v5_dap_cmd, "apid",
292 handle_dap_apid_command, COMMAND_EXEC,
293 "return id reg from AP [num], "
294 "default currently selected AP");
295 register_command(cmd_ctx, arm_adi_v5_dap_cmd, "baseaddr",
296 handle_dap_baseaddr_command, COMMAND_EXEC,
297 "return debug base address from AP [num], "
298 "default currently selected AP");
299 register_command(cmd_ctx, arm_adi_v5_dap_cmd, "memaccess",
300 handle_dap_memaccess_command, COMMAND_EXEC,
301 "set/get number of extra tck for mem-ap memory "
302 "bus access [0-255]");
303
304 return ERROR_OK;
305 }

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)