1 /*
2 * Support for processors implementing MIPS64 instruction set
3 *
4 * Copyright (C) 2014 by Andrey Sidorov <anysidorov@gmail.com>
5 * Copyright (C) 2014 by Aleksey Kuleshov <rndfax@yandex.ru>
6 * Copyright (C) 2014-2019 by Peter Mamonov <pmamonov@gmail.com>
7 *
8 * Based on the work of:
9 * Copyright (C) 2008 by Spencer Oliver
10 * Copyright (C) 2008 by David T.L. Wong
11 * Copyright (C) 2010 by Konstantin Kostyukhin, Nikolay Shmyrev
12 *
13 * SPDX-License-Identifier: GPL-2.0-or-later
14 */
15
16 #ifdef HAVE_CONFIG_H
17 #include "config.h"
18 #endif
19
20 #include "mips64.h"
21 #include "mips64_pracc.h"
22
23 #include "time_support.h"
24
25 #define STACK_DEPTH 32
26
27 typedef struct {
28 uint64_t *local_iparam;
29 unsigned num_iparam;
30 uint64_t *local_oparam;
31 unsigned num_oparam;
32 const uint32_t *code;
33 unsigned code_len;
34 uint64_t stack[STACK_DEPTH];
35 unsigned stack_offset;
36 struct mips_ejtag *ejtag_info;
37 } mips64_pracc_context;
38
wait_for_pracc_rw(struct mips_ejtag * ejtag_info,uint32_t * ctrl)39 static int wait_for_pracc_rw(struct mips_ejtag *ejtag_info, uint32_t *ctrl)
40 {
41 uint32_t ejtag_ctrl;
42 int nt = 5;
43 int rc;
44
45 while (1) {
46 mips_ejtag_set_instr(ejtag_info, EJTAG_INST_CONTROL);
47 ejtag_ctrl = ejtag_info->ejtag_ctrl;
48 rc = mips_ejtag_drscan_32(ejtag_info, &ejtag_ctrl);
49 if (rc != ERROR_OK)
50 return rc;
51
52 if (ejtag_ctrl & EJTAG_CTRL_PRACC)
53 break;
54 LOG_DEBUG("DEBUGMODULE: No memory access in progress!\n");
55 if (nt == 0)
56 return ERROR_JTAG_DEVICE_ERROR;
57 nt--;
58 }
59
60 *ctrl = ejtag_ctrl;
61 return ERROR_OK;
62 }
63
mips64_pracc_exec_read(mips64_pracc_context * ctx,uint64_t address)64 static int mips64_pracc_exec_read(mips64_pracc_context *ctx, uint64_t address)
65 {
66 struct mips_ejtag *ejtag_info = ctx->ejtag_info;
67 unsigned offset;
68 uint32_t ejtag_ctrl;
69 uint64_t data;
70 int rc;
71
72 if ((address >= MIPS64_PRACC_PARAM_IN)
73 && (address < MIPS64_PRACC_PARAM_IN + ctx->num_iparam * MIPS64_PRACC_DATA_STEP)) {
74
75 offset = (address - MIPS64_PRACC_PARAM_IN) / MIPS64_PRACC_DATA_STEP;
76
77 if (offset >= MIPS64_PRACC_PARAM_IN_SIZE) {
78 LOG_ERROR("Error: iparam size exceeds MIPS64_PRACC_PARAM_IN_SIZE");
79 return ERROR_JTAG_DEVICE_ERROR;
80 }
81
82 if (ctx->local_iparam == NULL) {
83 LOG_ERROR("Error: unexpected reading of input parameter");
84 return ERROR_JTAG_DEVICE_ERROR;
85 }
86
87 data = ctx->local_iparam[offset];
88 LOG_DEBUG("Reading %" PRIx64 " at %" PRIx64, data, address);
89
90 } else if ((address >= MIPS64_PRACC_PARAM_OUT)
91 && (address < MIPS64_PRACC_PARAM_OUT + ctx->num_oparam * MIPS64_PRACC_DATA_STEP)) {
92
93 offset = (address - MIPS64_PRACC_PARAM_OUT) / MIPS64_PRACC_DATA_STEP;
94 if (ctx->local_oparam == NULL) {
95 LOG_ERROR("Error: unexpected reading of output parameter");
96 return ERROR_JTAG_DEVICE_ERROR;
97 }
98
99 data = ctx->local_oparam[offset];
100 LOG_DEBUG("Reading %" PRIx64 " at %" PRIx64, data, address);
101
102 } else if ((address >= MIPS64_PRACC_TEXT)
103 && (address < MIPS64_PRACC_TEXT + ctx->code_len * MIPS64_PRACC_ADDR_STEP)) {
104
105 offset = ((address & ~7ull) - MIPS64_PRACC_TEXT) / MIPS64_PRACC_ADDR_STEP;
106 data = (uint64_t)ctx->code[offset] << 32;
107 if (offset + 1 < ctx->code_len)
108 data |= (uint64_t)ctx->code[offset + 1];
109
110 LOG_DEBUG("Running commands %" PRIx64 " at %" PRIx64, data,
111 address);
112
113 } else if ((address & ~7llu) == MIPS64_PRACC_STACK) {
114
115 /* load from our debug stack */
116 if (ctx->stack_offset == 0) {
117 LOG_ERROR("Error reading from stack: stack is empty");
118 return ERROR_JTAG_DEVICE_ERROR;
119 }
120
121 data = ctx->stack[--ctx->stack_offset];
122 LOG_DEBUG("Reading %" PRIx64 " at %" PRIx64, data, address);
123
124 } else {
125 /* TODO: send JMP 0xFF200000 instruction. Hopefully processor jump back
126 * to start of debug vector */
127
128 data = 0;
129 LOG_ERROR("Error reading unexpected address %" PRIx64, address);
130 return ERROR_JTAG_DEVICE_ERROR;
131 }
132
133 /* Send the data out */
134 mips_ejtag_set_instr(ctx->ejtag_info, EJTAG_INST_DATA);
135 rc = mips_ejtag_drscan_64(ctx->ejtag_info, &data);
136 if (rc != ERROR_OK)
137 return rc;
138
139 /* Clear the access pending bit (let the processor eat!) */
140
141 ejtag_ctrl = ejtag_info->ejtag_ctrl & ~EJTAG_CTRL_PRACC;
142 mips_ejtag_set_instr(ctx->ejtag_info, EJTAG_INST_CONTROL);
143 rc = mips_ejtag_drscan_32(ctx->ejtag_info, &ejtag_ctrl);
144 if (rc != ERROR_OK)
145 return rc;
146
147 jtag_add_clocks(5);
148
149 return jtag_execute_queue();
150 }
151
mips64_pracc_exec_write(mips64_pracc_context * ctx,uint64_t address)152 static int mips64_pracc_exec_write(mips64_pracc_context *ctx, uint64_t address)
153 {
154 uint32_t ejtag_ctrl;
155 uint64_t data;
156 unsigned offset;
157 struct mips_ejtag *ejtag_info = ctx->ejtag_info;
158 int rc;
159
160 mips_ejtag_set_instr(ctx->ejtag_info, EJTAG_INST_DATA);
161 rc = mips_ejtag_drscan_64(ctx->ejtag_info, &data);
162 if (rc != ERROR_OK)
163 return rc;
164
165 /* Clear access pending bit */
166 ejtag_ctrl = ejtag_info->ejtag_ctrl & ~EJTAG_CTRL_PRACC;
167 mips_ejtag_set_instr(ctx->ejtag_info, EJTAG_INST_CONTROL);
168 rc = mips_ejtag_drscan_32(ctx->ejtag_info, &ejtag_ctrl);
169 if (rc != ERROR_OK)
170 return rc;
171
172 jtag_add_clocks(5);
173 rc = jtag_execute_queue();
174 if (rc != ERROR_OK)
175 return rc;
176
177 LOG_DEBUG("Writing %" PRIx64 " at %" PRIx64, data, address);
178
179 if ((address >= MIPS64_PRACC_PARAM_IN)
180 && (address < MIPS64_PRACC_PARAM_IN + ctx->num_iparam * MIPS64_PRACC_DATA_STEP)) {
181 offset = (address - MIPS64_PRACC_PARAM_IN) / MIPS64_PRACC_DATA_STEP;
182 if (ctx->local_iparam == NULL) {
183 LOG_ERROR("Error: unexpected writing of input parameter");
184 return ERROR_JTAG_DEVICE_ERROR;
185 }
186 ctx->local_iparam[offset] = data;
187 } else if ((address >= MIPS64_PRACC_PARAM_OUT)
188 && (address < MIPS64_PRACC_PARAM_OUT + ctx->num_oparam * MIPS64_PRACC_DATA_STEP)) {
189 offset = (address - MIPS64_PRACC_PARAM_OUT) / MIPS64_PRACC_DATA_STEP;
190 if (ctx->local_oparam == NULL) {
191 LOG_ERROR("Error: unexpected writing of output parameter");
192 return ERROR_JTAG_DEVICE_ERROR;
193 }
194 ctx->local_oparam[offset] = data;
195 } else if (address == MIPS64_PRACC_STACK) {
196 /* save data onto our stack */
197 if (ctx->stack_offset >= STACK_DEPTH) {
198 LOG_ERROR("Error: PrAcc stack depth exceeded");
199 return ERROR_FAIL;
200 }
201 ctx->stack[ctx->stack_offset++] = data;
202 } else {
203 LOG_ERROR("Error writing unexpected address 0x%" PRIx64, address);
204 return ERROR_JTAG_DEVICE_ERROR;
205 }
206
207 return ERROR_OK;
208 }
209
mips64_pracc_exec(struct mips_ejtag * ejtag_info,unsigned code_len,const uint32_t * code,unsigned num_param_in,uint64_t * param_in,unsigned num_param_out,uint64_t * param_out)210 int mips64_pracc_exec(struct mips_ejtag *ejtag_info,
211 unsigned code_len, const uint32_t *code,
212 unsigned num_param_in, uint64_t *param_in,
213 unsigned num_param_out, uint64_t *param_out)
214 {
215 uint32_t ejtag_ctrl;
216 uint64_t address = 0, address_prev = 0, data;
217 mips64_pracc_context ctx;
218 int retval;
219 int pass = 0;
220 bool first_time_call = true;
221 unsigned i;
222
223 for (i = 0; i < code_len; i++)
224 LOG_DEBUG("%08" PRIx32, code[i]);
225
226 ctx.local_iparam = param_in;
227 ctx.local_oparam = param_out;
228 ctx.num_iparam = num_param_in;
229 ctx.num_oparam = num_param_out;
230 ctx.code = code;
231 ctx.code_len = code_len;
232 ctx.ejtag_info = ejtag_info;
233 ctx.stack_offset = 0;
234
235 while (true) {
236 uint32_t address32;
237 retval = wait_for_pracc_rw(ejtag_info, &ejtag_ctrl);
238 if (retval != ERROR_OK) {
239 LOG_DEBUG("ERROR wait_for_pracc_rw");
240 return retval;
241 }
242 if (pass)
243 address_prev = address;
244 else
245 address_prev = 0;
246 address32 = data = 0;
247
248 mips_ejtag_set_instr(ejtag_info, EJTAG_INST_ADDRESS);
249 mips_ejtag_drscan_32(ejtag_info, &address32);
250 LOG_DEBUG("-> %08" PRIx32, address32);
251 address = 0xffffffffff200000ull | address32;
252
253 int psz = (ejtag_ctrl >> 29) & 3;
254 int address20 = address & 7;
255 switch (psz) {
256 case 3:
257 if (address20 != 7) {
258 LOG_ERROR("PSZ=%d ADDRESS[2:0]=%d: not supported", psz, address20);
259 return ERROR_FAIL;
260 }
261 address &= ~7ull;
262 break;
263 case 2:
264 if (address20 != 0 && address20 != 4) {
265 LOG_ERROR("PSZ=%d ADDRESS[2:0]=%d: not supported", psz, address20);
266 return ERROR_FAIL;
267 }
268 break;
269 default:
270 LOG_ERROR("PSZ=%d ADDRESS[2:0]=%d: not supported", psz, address20);
271 return ERROR_FAIL;
272 }
273
274 if (first_time_call && address != MIPS64_PRACC_TEXT) {
275 LOG_ERROR("Error reading address " TARGET_ADDR_FMT " (0x%08llx expected)",
276 address, MIPS64_PRACC_TEXT);
277 return ERROR_JTAG_DEVICE_ERROR;
278 }
279
280 first_time_call = false;
281
282 /* Check for read or write */
283 if (ejtag_ctrl & EJTAG_CTRL_PRNW) {
284 retval = mips64_pracc_exec_write(&ctx, address);
285 if (retval != ERROR_OK) {
286 printf("ERROR mips64_pracc_exec_write\n");
287 return retval;
288 }
289 } else {
290 /* Check to see if its reading at the debug vector. The first pass through
291 * the module is always read at the vector, so the first one we allow. When
292 * the second read from the vector occurs we are done and just exit. */
293 if ((address == MIPS64_PRACC_TEXT) && (pass++)) {
294 LOG_DEBUG("@MIPS64_PRACC_TEXT, address_prev=%" PRIx64, address_prev);
295 break;
296 }
297 retval = mips64_pracc_exec_read(&ctx, address);
298 if (retval != ERROR_OK) {
299 printf("ERROR mips64_pracc_exec_read\n");
300 return retval;
301 }
302
303 }
304 }
305
306 /* stack sanity check */
307 if (ctx.stack_offset != 0)
308 LOG_ERROR("Pracc Stack not zero");
309
310 return ERROR_OK;
311 }
312
mips64_pracc_read_u64(struct mips_ejtag * ejtag_info,uint64_t addr,uint64_t * buf)313 static int mips64_pracc_read_u64(struct mips_ejtag *ejtag_info, uint64_t addr,
314 uint64_t *buf)
315 {
316 const uint32_t code[] = {
317 /* move $15 to COP0 DeSave */
318 MIPS64_DMTC0(15, 31, 0),
319 /* $15 = MIPS64_PRACC_STACK */
320 MIPS64_LUI(15, UPPER16(MIPS64_PRACC_STACK)),
321 MIPS64_ORI(15, 15, LOWER16(MIPS64_PRACC_STACK)),
322 /* sd $8, ($15) */
323 MIPS64_SD(8, 0, 15),
324 /* load R8 @ param_in[0] = address */
325 MIPS64_LD(8, NEG16(MIPS64_PRACC_STACK-MIPS64_PRACC_PARAM_IN), 15),
326 /* ld $8, 0($8), Load $8 with the word @mem[$8] */
327 MIPS64_LD(8, 0, 8),
328 /* sd $8, 0($15) */
329 MIPS64_SD(8, NEG16(MIPS64_PRACC_STACK-MIPS64_PRACC_PARAM_OUT), 15),
330 /* ld $8, ($15) */
331 MIPS64_LD(8, 0, 15),
332 MIPS64_SYNC,
333 /* b start */
334 MIPS64_B(NEG16(10)),
335 /* move COP0 DeSave to $15 */
336 MIPS64_DMFC0(15, 31, 0),
337 MIPS64_NOP,
338 MIPS64_NOP,
339 MIPS64_NOP,
340 MIPS64_NOP,
341 MIPS64_NOP,
342 MIPS64_NOP,
343 MIPS64_NOP,
344 MIPS64_NOP,
345 };
346
347 uint64_t param_in[1];
348 param_in[0] = addr;
349
350 LOG_DEBUG("enter mips64_pracc_exec");
351 return mips64_pracc_exec(ejtag_info, ARRAY_SIZE(code), code,
352 ARRAY_SIZE(param_in), param_in, 1, (uint64_t *) buf);
353 }
354
mips64_pracc_read_mem64(struct mips_ejtag * ejtag_info,uint64_t addr,unsigned count,uint64_t * buf)355 static int mips64_pracc_read_mem64(struct mips_ejtag *ejtag_info, uint64_t addr,
356 unsigned count, uint64_t *buf)
357 {
358 int retval = ERROR_OK;
359
360 for (unsigned i = 0; i < count; i++) {
361 retval = mips64_pracc_read_u64(ejtag_info, addr + 8*i, &buf[i]);
362 if (retval != ERROR_OK)
363 return retval;
364 }
365 return retval;
366 }
367
mips64_pracc_read_u32(struct mips_ejtag * ejtag_info,uint64_t addr,uint32_t * buf)368 static int mips64_pracc_read_u32(struct mips_ejtag *ejtag_info, uint64_t addr,
369 uint32_t *buf)
370 {
371 const uint32_t code[] = {
372 /* move $15 to COP0 DeSave */
373 MIPS64_DMTC0(15, 31, 0),
374 /* $15 = MIPS64_PRACC_STACK */
375 MIPS64_LUI(15, UPPER16(MIPS64_PRACC_STACK)),
376 MIPS64_ORI(15, 15, LOWER16(MIPS64_PRACC_STACK)),
377 /* sd $8, ($15) */
378 MIPS64_SD(8, 0, 15),
379 /* load R8 @ param_in[0] = address */
380 MIPS64_LD(8, NEG16(MIPS64_PRACC_STACK-MIPS64_PRACC_PARAM_IN), 15),
381 /* lw $8, 0($8), Load $8 with the word @mem[$8] */
382 MIPS64_LW(8, 0, 8),
383 /* sd $8, 0($9) */
384 MIPS64_SD(8, NEG16(MIPS64_PRACC_STACK-MIPS64_PRACC_PARAM_OUT), 15),
385 /* ld $8, ($15) */
386 MIPS64_LD(8, 0, 15),
387 MIPS64_SYNC,
388 /* b start */
389 MIPS64_B(NEG16(10)),
390 /* move COP0 DeSave to $15 */
391 MIPS64_DMFC0(15, 31, 0),
392 MIPS64_NOP,
393 MIPS64_NOP,
394 MIPS64_NOP,
395 MIPS64_NOP,
396 MIPS64_NOP,
397 MIPS64_NOP,
398 MIPS64_NOP,
399 MIPS64_NOP,
400 };
401
402 int retval = ERROR_OK;
403 uint64_t param_in[1];
404 uint64_t param_out[1];
405
406 param_in[0] = addr;
407
408 LOG_DEBUG("enter mips64_pracc_exec");
409 retval = mips64_pracc_exec(ejtag_info, ARRAY_SIZE(code), code,
410 1, param_in, 1, param_out);
411 buf[0] = (uint32_t) param_out[0];
412 return retval;
413 }
414
mips64_pracc_read_mem32(struct mips_ejtag * ejtag_info,uint64_t addr,unsigned count,uint32_t * buf)415 static int mips64_pracc_read_mem32(struct mips_ejtag *ejtag_info, uint64_t addr,
416 unsigned count, uint32_t *buf)
417 {
418 int retval = ERROR_OK;
419
420 for (unsigned i = 0; i < count; i++) {
421 retval = mips64_pracc_read_u32(ejtag_info, addr + 4 * i, &buf[i]);
422 if (retval != ERROR_OK)
423 return retval;
424 }
425 return retval;
426 }
427
mips64_pracc_read_u16(struct mips_ejtag * ejtag_info,uint64_t addr,uint16_t * buf)428 static int mips64_pracc_read_u16(struct mips_ejtag *ejtag_info, uint64_t addr,
429 uint16_t *buf)
430 {
431 const uint32_t code[] = {
432 /* move $15 to COP0 DeSave */
433 MIPS64_DMTC0(15, 31, 0),
434 /* $15 = MIPS64_PRACC_STACK */
435 MIPS64_LUI(15, UPPER16(MIPS64_PRACC_STACK)),
436 MIPS64_ORI(15, 15, LOWER16(MIPS64_PRACC_STACK)),
437 /* sd $8, ($15) */
438 MIPS64_SD(8, 0, 15),
439 /* load R8 @ param_in[0] = address */
440 MIPS64_LD(8, NEG16(MIPS64_PRACC_STACK-MIPS64_PRACC_PARAM_IN), 15),
441 /* lw $8, 0($8), Load $8 with the word @mem[$8] */
442 MIPS64_LHU(8, 0, 8),
443 /* sd $8, 0($9) */
444 MIPS64_SD(8, NEG16(MIPS64_PRACC_STACK-MIPS64_PRACC_PARAM_OUT), 15),
445 /* ld $8, ($15) */
446 MIPS64_LD(8, 0, 15),
447 MIPS64_SYNC,
448 /* b start */
449 MIPS64_B(NEG16(10)),
450 /* move COP0 DeSave to $15 */
451 MIPS64_DMFC0(15, 31, 0),
452 MIPS64_NOP,
453 MIPS64_NOP,
454 MIPS64_NOP,
455 MIPS64_NOP,
456 MIPS64_NOP,
457 MIPS64_NOP,
458 MIPS64_NOP,
459 MIPS64_NOP,
460 };
461
462 int retval;
463 uint64_t param_in[1];
464 uint64_t param_out[1];
465
466 param_in[0] = addr;
467
468 LOG_DEBUG("enter mips64_pracc_exec");
469 retval = mips64_pracc_exec(ejtag_info, ARRAY_SIZE(code), code,
470 1, param_in, 1, param_out);
471 buf[0] = (uint16_t)param_out[0];
472 return retval;
473 }
474
mips64_pracc_read_mem16(struct mips_ejtag * ejtag_info,uint64_t addr,unsigned count,uint16_t * buf)475 static int mips64_pracc_read_mem16(struct mips_ejtag *ejtag_info, uint64_t addr,
476 unsigned count, uint16_t *buf)
477 {
478 int retval = ERROR_OK;
479
480 for (unsigned i = 0; i < count; i++) {
481 retval = mips64_pracc_read_u16(ejtag_info, addr + 2*i, &buf[i]);
482 if (retval != ERROR_OK)
483 return retval;
484 }
485 return retval;
486 }
487
mips64_pracc_read_u8(struct mips_ejtag * ejtag_info,uint64_t addr,uint8_t * buf)488 static int mips64_pracc_read_u8(struct mips_ejtag *ejtag_info, uint64_t addr,
489 uint8_t *buf)
490 {
491 const uint32_t code[] = {
492 /* move $15 to COP0 DeSave */
493 MIPS64_DMTC0(15, 31, 0),
494 /* $15 = MIPS64_PRACC_STACK */
495 MIPS64_LUI(15, UPPER16(MIPS64_PRACC_STACK)),
496 MIPS64_ORI(15, 15, LOWER16(MIPS64_PRACC_STACK)),
497 /* sd $8, ($15) */
498 MIPS64_SD(8, 0, 15),
499 /* load R8 @ param_in[0] = address */
500 MIPS64_LD(8, NEG16(MIPS64_PRACC_STACK-MIPS64_PRACC_PARAM_IN), 15),
501 /* lw $8, 0($8), Load $8 with the word @mem[$8] */
502 MIPS64_LBU(8, 0, 8),
503 /* sd $8, 0($9) */
504 MIPS64_SD(8, NEG16(MIPS64_PRACC_STACK-MIPS64_PRACC_PARAM_OUT), 15),
505 /* ld $8, ($15) */
506 MIPS64_LD(8, 0, 15),
507 MIPS64_SYNC,
508 /* b start */
509 MIPS64_B(NEG16(10)),
510 /* move COP0 DeSave to $15 */
511 MIPS64_DMFC0(15, 31, 0),
512 MIPS64_NOP,
513 MIPS64_NOP,
514 MIPS64_NOP,
515 MIPS64_NOP,
516 MIPS64_NOP,
517 MIPS64_NOP,
518 MIPS64_NOP,
519 MIPS64_NOP,
520 };
521
522 int retval;
523 uint64_t param_in[1];
524 uint64_t param_out[1];
525
526 param_in[0] = addr;
527
528 LOG_DEBUG("enter mips64_pracc_exec");
529 retval = mips64_pracc_exec(ejtag_info, ARRAY_SIZE(code), code,
530 1, param_in, 1, param_out);
531 buf[0] = (uint8_t)param_out[0];
532 return retval;
533 }
534
mips64_pracc_read_mem8(struct mips_ejtag * ejtag_info,uint64_t addr,unsigned count,uint8_t * buf)535 static int mips64_pracc_read_mem8(struct mips_ejtag *ejtag_info, uint64_t addr,
536 unsigned count, uint8_t *buf)
537 {
538 int retval = ERROR_OK;
539
540 for (unsigned i = 0; i < count; i++) {
541 retval = mips64_pracc_read_u8(ejtag_info, addr + i, &buf[i]);
542 if (retval != ERROR_OK)
543 return retval;
544 }
545 return retval;
546 }
547
mips64_pracc_read_mem(struct mips_ejtag * ejtag_info,uint64_t addr,unsigned size,unsigned count,void * buf)548 int mips64_pracc_read_mem(struct mips_ejtag *ejtag_info, uint64_t addr,
549 unsigned size, unsigned count, void *buf)
550 {
551 switch (size) {
552 case 1:
553 return mips64_pracc_read_mem8(ejtag_info, addr, count, buf);
554 case 2:
555 return mips64_pracc_read_mem16(ejtag_info, addr, count, buf);
556 case 4:
557 return mips64_pracc_read_mem32(ejtag_info, addr, count, buf);
558 case 8:
559 return mips64_pracc_read_mem64(ejtag_info, addr, count, buf);
560 }
561 return ERROR_FAIL;
562 }
563
mips64_pracc_write_u64(struct mips_ejtag * ejtag_info,uint64_t addr,uint64_t * buf)564 static int mips64_pracc_write_u64(struct mips_ejtag *ejtag_info, uint64_t addr,
565 uint64_t *buf)
566 {
567 const uint32_t code[] = {
568 /* move $15 to COP0 DeSave */
569 MIPS64_DMTC0(15, 31, 0),
570 /* $15 = MIPS64_PRACC_STACK */
571 MIPS64_LUI(15, UPPER16(MIPS64_PRACC_STACK)),
572 MIPS64_ORI(15, 15, LOWER16(MIPS64_PRACC_STACK)),
573 /* sd $8, ($15) */
574 MIPS64_SD(8, 0, 15),
575 /* sd $9, ($15) */
576 MIPS64_SD(9, 0, 15),
577 /* load R8 @ param_in[1] = data */
578 MIPS64_LD(8, NEG16((MIPS64_PRACC_STACK-MIPS64_PRACC_PARAM_IN)-8), 15),
579 /* load R9 @ param_in[0] = address */
580 MIPS64_LD(9, NEG16(MIPS64_PRACC_STACK-MIPS64_PRACC_PARAM_IN), 15),
581 /* sd $8, 0($9) */
582 MIPS64_SD(8, 0, 9),
583 MIPS64_SYNCI(9, 0),
584 /* ld $9, ($15) */
585 MIPS64_LD(9, 0, 15),
586 /* ld $8, ($15) */
587 MIPS64_LD(8, 0, 15),
588 MIPS64_SYNC,
589 /* b start */
590 MIPS64_B(NEG16(13)),
591 /* move COP0 DeSave to $15 */
592 MIPS64_DMFC0(15, 31, 0),
593 MIPS64_NOP,
594 MIPS64_NOP,
595 MIPS64_NOP,
596 MIPS64_NOP,
597 MIPS64_NOP,
598 MIPS64_NOP,
599 MIPS64_NOP,
600 MIPS64_NOP,
601 };
602
603 /* TODO remove array */
604 uint64_t param_in[2];
605 param_in[0] = addr;
606 param_in[1] = *buf;
607
608 LOG_DEBUG("enter mips64_pracc_exec");
609 return mips64_pracc_exec(ejtag_info, ARRAY_SIZE(code), code,
610 ARRAY_SIZE(param_in), param_in, 0, NULL);
611 }
612
mips64_pracc_write_mem64(struct mips_ejtag * ejtag_info,uint64_t addr,unsigned count,uint64_t * buf)613 static int mips64_pracc_write_mem64(struct mips_ejtag *ejtag_info,
614 uint64_t addr, unsigned count, uint64_t *buf)
615 {
616 int retval = ERROR_OK;
617
618 for (unsigned i = 0; i < count; i++) {
619 retval = mips64_pracc_write_u64(ejtag_info, addr + 8 * i, &buf[i]);
620 if (retval != ERROR_OK)
621 return retval;
622 }
623 return retval;
624 }
625
mips64_pracc_write_u32(struct mips_ejtag * ejtag_info,uint64_t addr,uint32_t * buf)626 static int mips64_pracc_write_u32(struct mips_ejtag *ejtag_info, uint64_t addr,
627 uint32_t *buf)
628 {
629 const uint32_t code[] = {
630 MIPS64_DMTC0(15, 31, 0),
631 /* move $15 to COP0 DeSave */
632 MIPS64_LUI(15, UPPER16(MIPS64_PRACC_STACK)),
633 /* $15 = MIPS64_PRACC_STACK */
634 MIPS64_ORI(15, 15, LOWER16(MIPS64_PRACC_STACK)),
635 MIPS64_SD(8, 0, 15),
636 /* sd $8, ($15) */
637 MIPS64_SD(9, 0, 15),
638 /* sd $9, ($15) */
639 MIPS64_LD(8, NEG16((MIPS64_PRACC_STACK-MIPS64_PRACC_PARAM_IN) - 8), 15),
640 /* load R8 @ param_in[1] = data */
641 MIPS64_LD(9, NEG16(MIPS64_PRACC_STACK-MIPS64_PRACC_PARAM_IN), 15),
642 /* load R9 @ param_in[0] = address */
643 MIPS64_SW(8, 0, 9),
644 /* sw $8, 0($9) */
645 MIPS64_SYNCI(9, 0),
646 MIPS64_LD(9, 0, 15),
647 /* ld $9, ($15) */
648 MIPS64_LD(8, 0, 15),
649 /* ld $8, ($15) */
650 MIPS64_SYNC,
651 MIPS64_B(NEG16(13)),
652 /* b start */
653 MIPS64_DMFC0(15, 31, 0),
654 /* move COP0 DeSave to $15 */
655 MIPS64_NOP,
656 MIPS64_NOP,
657 MIPS64_NOP,
658 MIPS64_NOP,
659 MIPS64_NOP,
660 MIPS64_NOP,
661 MIPS64_NOP,
662 MIPS64_NOP,
663 };
664
665 /* TODO remove array */
666 uint64_t param_in[1 + 1];
667 param_in[0] = addr;
668 param_in[1] = *buf;
669
670 LOG_DEBUG("enter mips64_pracc_exec");
671 return mips64_pracc_exec(ejtag_info, ARRAY_SIZE(code), code,
672 ARRAY_SIZE(param_in), param_in, 0, NULL);
673 }
674
mips64_pracc_write_mem32(struct mips_ejtag * ejtag_info,uint64_t addr,unsigned count,uint32_t * buf)675 static int mips64_pracc_write_mem32(struct mips_ejtag *ejtag_info, uint64_t addr,
676 unsigned count, uint32_t *buf)
677 {
678 int retval = ERROR_OK;
679
680 for (unsigned i = 0; i < count; i++) {
681 retval = mips64_pracc_write_u32(ejtag_info, addr + 4 * i, &buf[i]);
682 if (retval != ERROR_OK)
683 return retval;
684 }
685 return retval;
686 }
687
mips64_pracc_write_u16(struct mips_ejtag * ejtag_info,uint64_t addr,uint16_t * buf)688 static int mips64_pracc_write_u16(struct mips_ejtag *ejtag_info, uint64_t addr,
689 uint16_t *buf)
690 {
691 const uint32_t code[] = {
692 /* move $15 to COP0 DeSave */
693 MIPS64_DMTC0(15, 31, 0),
694 /* $15 = MIPS64_PRACC_STACK */
695 MIPS64_LUI(15, UPPER16(MIPS64_PRACC_STACK)),
696 MIPS64_ORI(15, 15, LOWER16(MIPS64_PRACC_STACK)),
697 /* sd $8, ($15) */
698 MIPS64_SD(8, 0, 15),
699 /* sd $9, ($15) */
700 MIPS64_SD(9, 0, 15),
701 /* load R8 @ param_in[1] = data */
702 MIPS64_LD(8, NEG16((MIPS64_PRACC_STACK-MIPS64_PRACC_PARAM_IN) - 8), 15),
703 /* load R9 @ param_in[0] = address */
704 MIPS64_LD(9, NEG16(MIPS64_PRACC_STACK-MIPS64_PRACC_PARAM_IN), 15),
705 /* sh $8, 0($9) */
706 MIPS64_SH(8, 0, 9),
707 /* ld $9, ($15) */
708 MIPS64_LD(9, 0, 15),
709 /* ld $8, ($15) */
710 MIPS64_LD(8, 0, 15),
711 MIPS64_SYNC,
712 /* b start */
713 MIPS64_B(NEG16(12)),
714 /* move COP0 DeSave to $15 */
715 MIPS64_DMFC0(15, 31, 0),
716 MIPS64_NOP,
717 MIPS64_NOP,
718 MIPS64_NOP,
719 MIPS64_NOP,
720 MIPS64_NOP,
721 MIPS64_NOP,
722 MIPS64_NOP,
723 MIPS64_NOP,
724 };
725
726 uint64_t param_in[2];
727 param_in[0] = addr;
728 param_in[1] = *buf;
729
730 LOG_DEBUG("enter mips64_pracc_exec");
731 return mips64_pracc_exec(ejtag_info, ARRAY_SIZE(code), code,
732 ARRAY_SIZE(param_in), param_in, 0, NULL);
733 }
734
mips64_pracc_write_mem16(struct mips_ejtag * ejtag_info,uint64_t addr,unsigned count,uint16_t * buf)735 static int mips64_pracc_write_mem16(struct mips_ejtag *ejtag_info,
736 uint64_t addr, unsigned count, uint16_t *buf)
737 {
738 int retval = ERROR_OK;
739
740 for (unsigned i = 0; i < count; i++) {
741 retval = mips64_pracc_write_u16(ejtag_info, addr + 2 * i, &buf[i]);
742 if (retval != ERROR_OK)
743 return retval;
744 }
745 return retval;
746 }
747
mips64_pracc_write_u8(struct mips_ejtag * ejtag_info,uint64_t addr,uint8_t * buf)748 static int mips64_pracc_write_u8(struct mips_ejtag *ejtag_info, uint64_t addr,
749 uint8_t *buf)
750 {
751 const uint32_t code[] = {
752 /* move $15 to COP0 DeSave */
753 MIPS64_DMTC0(15, 31, 0),
754 /* $15 = MIPS64_PRACC_STACK */
755 MIPS64_LUI(15, UPPER16(MIPS64_PRACC_STACK)),
756 MIPS64_ORI(15, 15, LOWER16(MIPS64_PRACC_STACK)),
757 /* sd $8, ($15) */
758 MIPS64_SD(8, 0, 15),
759 /* sd $9, ($15) */
760 MIPS64_SD(9, 0, 15),
761 /* load R8 @ param_in[1] = data */
762 MIPS64_LD(8, NEG16((MIPS64_PRACC_STACK-MIPS64_PRACC_PARAM_IN) - 8), 15),
763 /* load R9 @ param_in[0] = address */
764 MIPS64_LD(9, NEG16(MIPS64_PRACC_STACK-MIPS64_PRACC_PARAM_IN), 15),
765 /* sh $8, 0($9) */
766 MIPS64_SB(8, 0, 9),
767 /* ld $9, ($15) */
768 MIPS64_LD(9, 0, 15),
769 /* ld $8, ($15) */
770 MIPS64_LD(8, 0, 15),
771 MIPS64_SYNC,
772 /* b start */
773 MIPS64_B(NEG16(12)),
774 /* move COP0 DeSave to $15 */
775 MIPS64_DMFC0(15, 31, 0),
776 MIPS64_NOP,
777 MIPS64_NOP,
778 MIPS64_NOP,
779 MIPS64_NOP,
780 MIPS64_NOP,
781 MIPS64_NOP,
782 MIPS64_NOP,
783 MIPS64_NOP,
784 };
785
786 /* TODO remove array */
787 uint64_t param_in[2];
788 param_in[0] = addr;
789 param_in[1] = *buf;
790
791 LOG_DEBUG("enter mips64_pracc_exec");
792 return mips64_pracc_exec(ejtag_info, ARRAY_SIZE(code), code,
793 ARRAY_SIZE(param_in), param_in, 0, NULL);
794 }
795
mips64_pracc_write_mem8(struct mips_ejtag * ejtag_info,uint64_t addr,unsigned count,uint8_t * buf)796 static int mips64_pracc_write_mem8(struct mips_ejtag *ejtag_info,
797 uint64_t addr, unsigned count, uint8_t *buf)
798 {
799 int retval = ERROR_OK;
800
801 for (unsigned i = 0; i < count; i++) {
802 retval = mips64_pracc_write_u8(ejtag_info, addr + i, &buf[i]);
803 if (retval != ERROR_OK)
804 return retval;
805 }
806 return retval;
807 }
808
mips64_pracc_write_mem(struct mips_ejtag * ejtag_info,uint64_t addr,unsigned size,unsigned count,void * buf)809 int mips64_pracc_write_mem(struct mips_ejtag *ejtag_info,
810 uint64_t addr, unsigned size,
811 unsigned count, void *buf)
812 {
813 switch (size) {
814 case 1:
815 return mips64_pracc_write_mem8(ejtag_info, addr, count, buf);
816 case 2:
817 return mips64_pracc_write_mem16(ejtag_info, addr, count, buf);
818 case 4:
819 return mips64_pracc_write_mem32(ejtag_info, addr, count, buf);
820 case 8:
821 return mips64_pracc_write_mem64(ejtag_info, addr, count, buf);
822 }
823 return ERROR_FAIL;
824 }
825
mips64_pracc_write_regs(struct mips_ejtag * ejtag_info,uint64_t * regs)826 int mips64_pracc_write_regs(struct mips_ejtag *ejtag_info, uint64_t *regs)
827 {
828 const uint32_t code[] = {
829 /* move $2 to COP0 DeSave */
830 MIPS64_DMTC0(2, 31, 0),
831 /* $15 = MIPS64_PRACC_STACK */
832 MIPS64_LUI(2, UPPER16(MIPS64_PRACC_PARAM_IN)),
833 MIPS64_ORI(2, 2, LOWER16(MIPS64_PRACC_PARAM_IN)),
834 /* sd $0, 0*8($2) */
835 MIPS64_LD(1, 1*8, 2),
836 /* sd $1, 1*8($2) */
837 MIPS64_LD(15, 15*8, 2),
838 /* sd $11, ($15) */
839 MIPS64_DMFC0(2, 31, 0),
840 MIPS64_DMTC0(15, 31, 0),
841 MIPS64_LUI(15, UPPER16(MIPS64_PRACC_STACK)),
842 MIPS64_ORI(15, 15, LOWER16(MIPS64_PRACC_STACK)),
843 MIPS64_SD(1, 0, 15),
844 /* $11 = MIPS64_PRACC_PARAM_OUT */
845 MIPS64_LUI(1, UPPER16(MIPS64_PRACC_PARAM_IN)),
846 MIPS64_ORI(1, 1, LOWER16(MIPS64_PRACC_PARAM_IN)),
847 MIPS64_LD(3, 3*8, 1),
848 MIPS64_LD(4, 4*8, 1),
849 MIPS64_LD(5, 5*8, 1),
850 MIPS64_LD(6, 6*8, 1),
851 MIPS64_LD(7, 7*8, 1),
852 MIPS64_LD(8, 8*8, 1),
853 MIPS64_LD(9, 9*8, 1),
854 MIPS64_LD(10, 10*8, 1),
855 MIPS64_LD(11, 11*8, 1),
856 MIPS64_LD(12, 12*8, 1),
857 MIPS64_LD(13, 13*8, 1),
858 MIPS64_LD(14, 14*8, 1),
859 MIPS64_LD(16, 16*8, 1),
860 MIPS64_LD(17, 17*8, 1),
861 MIPS64_LD(18, 18*8, 1),
862 MIPS64_LD(19, 19*8, 1),
863 MIPS64_LD(20, 20*8, 1),
864 MIPS64_LD(21, 21*8, 1),
865 MIPS64_LD(22, 22*8, 1),
866 MIPS64_LD(23, 23*8, 1),
867 MIPS64_LD(24, 24*8, 1),
868 MIPS64_LD(25, 25*8, 1),
869 MIPS64_LD(26, 26*8, 1),
870 MIPS64_LD(27, 27*8, 1),
871 MIPS64_LD(28, 28*8, 1),
872 MIPS64_LD(29, 29*8, 1),
873 MIPS64_LD(30, 30*8, 1),
874 MIPS64_LD(31, 31*8, 1),
875 MIPS64_LD(2, 32*8, 1),
876 MIPS64_MTLO(2),
877 MIPS64_LD(2, 33*8, 1),
878 MIPS64_MTHI(2),
879 MIPS64_LD(2, MIPS64_NUM_CORE_REGS * 8, 1),
880 MIPS64_DMTC0(2, MIPS64_C0_DEPC, 0),
881 MIPS64_LD(2, (MIPS64_NUM_CORE_REGS + 2) * 8, 1),
882 MIPS64_DMTC0(2, MIPS64_C0_ENTRYLO0, 0),
883 MIPS64_LD(2, (MIPS64_NUM_CORE_REGS + 3) * 8, 1),
884 MIPS64_DMTC0(2, MIPS64_C0_ENTRYLO1, 0),
885 MIPS64_LD(2, (MIPS64_NUM_CORE_REGS + 4) * 8, 1),
886 MIPS64_DMTC0(2, MIPS64_C0_CONTEXT, 0),
887 MIPS64_LD(2, (MIPS64_NUM_CORE_REGS + 5) * 8, 1),
888 MIPS64_MTC0(2, MIPS64_C0_PAGEMASK, 0),
889 MIPS64_LD(2, (MIPS64_NUM_CORE_REGS + 6) * 8, 1),
890 MIPS64_MTC0(2, MIPS64_C0_WIRED, 0),
891 MIPS64_LD(2, (MIPS64_NUM_CORE_REGS + 8) * 8, 1),
892 MIPS64_MTC0(2, MIPS64_C0_COUNT, 0),
893 MIPS64_LD(2, (MIPS64_NUM_CORE_REGS + 9) * 8, 1),
894 MIPS64_DMTC0(2, MIPS64_C0_ENTRYHI, 0),
895 MIPS64_LD(2, (MIPS64_NUM_CORE_REGS + 10) * 8, 1),
896 MIPS64_MTC0(2, MIPS64_C0_COMPARE, 0),
897 MIPS64_LD(2, (MIPS64_NUM_CORE_REGS + 11) * 8, 1),
898 MIPS64_MTC0(2, MIPS64_C0_STATUS, 0),
899 MIPS64_LD(2, (MIPS64_NUM_CORE_REGS + 12) * 8, 1),
900 MIPS64_MTC0(2, MIPS64_C0_CAUSE, 0),
901 MIPS64_LD(2, (MIPS64_NUM_CORE_REGS + 13) * 8, 1),
902 MIPS64_DMTC0(2, MIPS64_C0_EPC, 0),
903 MIPS64_LD(2, (MIPS64_NUM_CORE_REGS + 15) * 8, 1),
904 MIPS64_MTC0(2, MIPS64_C0_CONFIG, 0),
905 MIPS64_LD(2, (MIPS64_NUM_CORE_REGS + 16) * 8, 1),
906 MIPS64_MTC0(2, MIPS64_C0_LLA, 0),
907 MIPS64_LD(2, (MIPS64_NUM_CORE_REGS + 21) * 8, 1),
908 MIPS64_DMTC0(2, MIPS64_C0_XCONTEXT, 1),
909 MIPS64_LD(2, (MIPS64_NUM_CORE_REGS + 22) * 8, 1),
910 MIPS64_MTC0(2, MIPS64_C0_MEMCTRL, 0),
911 MIPS64_LD(2, (MIPS64_NUM_CORE_REGS + 24) * 8, 1),
912 MIPS64_MTC0(2, MIPS64_C0_PERFCOUNT, 0),
913 MIPS64_LD(2, (MIPS64_NUM_CORE_REGS + 25) * 8, 1),
914 MIPS64_MTC0(2, MIPS64_C0_PERFCOUNT, 1),
915 MIPS64_LD(2, (MIPS64_NUM_CORE_REGS + 26) * 8, 1),
916 MIPS64_MTC0(2, MIPS64_C0_PERFCOUNT, 2),
917 MIPS64_LD(2, (MIPS64_NUM_CORE_REGS + 27) * 8, 1),
918 MIPS64_MTC0(2, MIPS64_C0_PERFCOUNT, 3),
919 MIPS64_LD(2, (MIPS64_NUM_CORE_REGS + 28) * 8, 1),
920 MIPS64_MTC0(2, MIPS64_C0_ECC, 0),
921 MIPS64_LD(2, (MIPS64_NUM_CORE_REGS + 29) * 8, 1),
922 MIPS64_MTC0(2, MIPS64_C0_CACHERR, 0),
923 MIPS64_LD(2, (MIPS64_NUM_CORE_REGS + 30) * 8, 1),
924 MIPS64_MTC0(2, MIPS64_C0_TAGLO, 0),
925 MIPS64_LD(2, (MIPS64_NUM_CORE_REGS + 31) * 8, 1),
926 MIPS64_MTC0(2, MIPS64_C0_TAGHI, 0),
927 MIPS64_LD(2, (MIPS64_NUM_CORE_REGS + 32) * 8, 1),
928 MIPS64_DMTC0(2, MIPS64_C0_DATAHI, 0),
929 MIPS64_LD(2, (MIPS64_NUM_CORE_REGS + 33) * 8, 1),
930 MIPS64_DMTC0(2, MIPS64_C0_EEPC, 0),
931 /* check if FPU is enabled, */
932 MIPS64_MFC0(2, MIPS64_C0_STATUS, 0),
933 MIPS64_SRL(2, 2, 29),
934 MIPS64_ANDI(2, 2, 1),
935 /* skip FPU registers restoration if not */
936 MIPS64_BEQ(0, 2, 77),
937 MIPS64_NOP,
938 MIPS64_LD(2, (MIPS64_NUM_CORE_C0_REGS + 33) * 8, 1),
939 MIPS64_CTC1(2, MIPS64_C1_FIR, 0),
940 MIPS64_LD(2, (MIPS64_NUM_CORE_C0_REGS + 32) * 8, 1),
941 MIPS64_CTC1(2, MIPS64_C1_FCSR, 0),
942 MIPS64_LD(2, (MIPS64_NUM_CORE_C0_REGS + 34) * 8, 1),
943 MIPS64_CTC1(2, MIPS64_C1_FCONFIG, 0),
944 MIPS64_LD(2, (MIPS64_NUM_CORE_C0_REGS + 35) * 8, 1),
945 MIPS64_CTC1(2, MIPS64_C1_FCCR, 0),
946 MIPS64_LD(2, (MIPS64_NUM_CORE_C0_REGS + 36) * 8, 1),
947 MIPS64_CTC1(2, MIPS64_C1_FEXR, 0),
948 MIPS64_LD(2, (MIPS64_NUM_CORE_C0_REGS + 37) * 8, 1),
949 MIPS64_CTC1(2, MIPS64_C1_FENR, 0),
950 MIPS64_LD(2, (MIPS64_NUM_CORE_C0_REGS + 0) * 8, 1),
951 MIPS64_DMTC1(2, 0, 0),
952 MIPS64_LD(2, (MIPS64_NUM_CORE_C0_REGS + 1) * 8, 1),
953 MIPS64_DMTC1(2, 1, 0),
954 MIPS64_LD(2, (MIPS64_NUM_CORE_C0_REGS + 2) * 8, 1),
955 MIPS64_DMTC1(2, 2, 0),
956 MIPS64_LD(2, (MIPS64_NUM_CORE_C0_REGS + 3) * 8, 1),
957 MIPS64_DMTC1(2, 3, 0),
958 MIPS64_LD(2, (MIPS64_NUM_CORE_C0_REGS + 4) * 8, 1),
959 MIPS64_DMTC1(2, 4, 0),
960 MIPS64_LD(2, (MIPS64_NUM_CORE_C0_REGS + 5) * 8, 1),
961 MIPS64_DMTC1(2, 5, 0),
962 MIPS64_LD(2, (MIPS64_NUM_CORE_C0_REGS + 6) * 8, 1),
963 MIPS64_DMTC1(2, 6, 0),
964 MIPS64_LD(2, (MIPS64_NUM_CORE_C0_REGS + 7) * 8, 1),
965 MIPS64_DMTC1(2, 7, 0),
966 MIPS64_LD(2, (MIPS64_NUM_CORE_C0_REGS + 8) * 8, 1),
967 MIPS64_DMTC1(2, 8, 0),
968 MIPS64_LD(2, (MIPS64_NUM_CORE_C0_REGS + 9) * 8, 1),
969 MIPS64_DMTC1(2, 9, 0),
970 MIPS64_LD(2, (MIPS64_NUM_CORE_C0_REGS + 10) * 8, 1),
971 MIPS64_DMTC1(2, 10, 0),
972 MIPS64_LD(2, (MIPS64_NUM_CORE_C0_REGS + 11) * 8, 1),
973 MIPS64_DMTC1(2, 11, 0),
974 MIPS64_LD(2, (MIPS64_NUM_CORE_C0_REGS + 12) * 8, 1),
975 MIPS64_DMTC1(2, 12, 0),
976 MIPS64_LD(2, (MIPS64_NUM_CORE_C0_REGS + 13) * 8, 1),
977 MIPS64_DMTC1(2, 13, 0),
978 MIPS64_LD(2, (MIPS64_NUM_CORE_C0_REGS + 14) * 8, 1),
979 MIPS64_DMTC1(2, 14, 0),
980 MIPS64_LD(2, (MIPS64_NUM_CORE_C0_REGS + 15) * 8, 1),
981 MIPS64_DMTC1(2, 15, 0),
982 MIPS64_LD(2, (MIPS64_NUM_CORE_C0_REGS + 16) * 8, 1),
983 MIPS64_DMTC1(2, 16, 0),
984 MIPS64_LD(2, (MIPS64_NUM_CORE_C0_REGS + 17) * 8, 1),
985 MIPS64_DMTC1(2, 17, 0),
986 MIPS64_LD(2, (MIPS64_NUM_CORE_C0_REGS + 18) * 8, 1),
987 MIPS64_DMTC1(2, 18, 0),
988 MIPS64_LD(2, (MIPS64_NUM_CORE_C0_REGS + 19) * 8, 1),
989 MIPS64_DMTC1(2, 19, 0),
990 MIPS64_LD(2, (MIPS64_NUM_CORE_C0_REGS + 20) * 8, 1),
991 MIPS64_DMTC1(2, 20, 0),
992 MIPS64_LD(2, (MIPS64_NUM_CORE_C0_REGS + 21) * 8, 1),
993 MIPS64_DMTC1(2, 21, 0),
994 MIPS64_LD(2, (MIPS64_NUM_CORE_C0_REGS + 22) * 8, 1),
995 MIPS64_DMTC1(2, 22, 0),
996 MIPS64_LD(2, (MIPS64_NUM_CORE_C0_REGS + 23) * 8, 1),
997 MIPS64_DMTC1(2, 23, 0),
998 MIPS64_LD(2, (MIPS64_NUM_CORE_C0_REGS + 24) * 8, 1),
999 MIPS64_DMTC1(2, 24, 0),
1000 MIPS64_LD(2, (MIPS64_NUM_CORE_C0_REGS + 25) * 8, 1),
1001 MIPS64_DMTC1(2, 25, 0),
1002 MIPS64_LD(2, (MIPS64_NUM_CORE_C0_REGS + 26) * 8, 1),
1003 MIPS64_DMTC1(2, 26, 0),
1004 MIPS64_LD(2, (MIPS64_NUM_CORE_C0_REGS + 27) * 8, 1),
1005 MIPS64_DMTC1(2, 27, 0),
1006 MIPS64_LD(2, (MIPS64_NUM_CORE_C0_REGS + 28) * 8, 1),
1007 MIPS64_DMTC1(2, 28, 0),
1008 MIPS64_LD(2, (MIPS64_NUM_CORE_C0_REGS + 29) * 8, 1),
1009 MIPS64_DMTC1(2, 29, 0),
1010 MIPS64_LD(2, (MIPS64_NUM_CORE_C0_REGS + 30) * 8, 1),
1011 MIPS64_DMTC1(2, 30, 0),
1012 MIPS64_LD(2, (MIPS64_NUM_CORE_C0_REGS + 31) * 8, 1),
1013 MIPS64_DMTC1(2, 31, 0),
1014 MIPS64_LD(2, 2 * 8, 1),
1015 MIPS64_LD(1, 0, 15),
1016 MIPS64_SYNC,
1017 /* b start */
1018 MIPS64_B(NEG16(181)),
1019 /* move COP0 DeSave to $15 */
1020 MIPS64_DMFC0(15, 31, 0),
1021 MIPS64_NOP,
1022 MIPS64_NOP,
1023 MIPS64_NOP,
1024 MIPS64_NOP,
1025 MIPS64_NOP,
1026 MIPS64_NOP,
1027 MIPS64_NOP,
1028 MIPS64_NOP,
1029 };
1030
1031 LOG_DEBUG("enter mips64_pracc_exec");
1032 return mips64_pracc_exec(ejtag_info, ARRAY_SIZE(code), code,
1033 MIPS64_NUM_REGS, regs, 0, NULL);
1034 }
1035
mips64_pracc_read_regs(struct mips_ejtag * ejtag_info,uint64_t * regs)1036 int mips64_pracc_read_regs(struct mips_ejtag *ejtag_info, uint64_t *regs)
1037 {
1038 const uint32_t code[] = {
1039 /* move $2 to COP0 DeSave */
1040 MIPS64_DMTC0(2, 31, 0),
1041 /* $2 = MIPS64_PRACC_PARAM_OUT */
1042 MIPS64_LUI(2, UPPER16(MIPS64_PRACC_PARAM_OUT)),
1043 MIPS64_ORI(2, 2, LOWER16(MIPS64_PRACC_PARAM_OUT)),
1044 /* sd $0, 0*8($2) */
1045 MIPS64_SD(0, 0*8, 2),
1046 /* sd $1, 1*8($2) */
1047 MIPS64_SD(1, 1*8, 2),
1048 /* sd $15, 15*8($2) */
1049 MIPS64_SD(15, 15*8, 2),
1050 /* move COP0 DeSave to $2 */
1051 MIPS64_DMFC0(2, 31, 0),
1052 /* move $15 to COP0 DeSave */
1053 MIPS64_DMTC0(15, 31, 0),
1054 /* $15 = MIPS64_PRACC_STACK */
1055 MIPS64_LUI(15, UPPER16(MIPS64_PRACC_STACK)),
1056 MIPS64_ORI(15, 15, LOWER16(MIPS64_PRACC_STACK)),
1057 /* sd $1, ($15) */
1058 MIPS64_SD(1, 0, 15),
1059 /* sd $2, ($15) */
1060 MIPS64_SD(2, 0, 15),
1061 /* $1 = MIPS64_PRACC_PARAM_OUT */
1062 MIPS64_LUI(1, UPPER16(MIPS64_PRACC_PARAM_OUT)),
1063 MIPS64_ORI(1, 1, LOWER16(MIPS64_PRACC_PARAM_OUT)),
1064 MIPS64_SD(2, 2 * 8, 1),
1065 MIPS64_SD(3, 3 * 8, 1),
1066 MIPS64_SD(4, 4 * 8, 1),
1067 MIPS64_SD(5, 5 * 8, 1),
1068 MIPS64_SD(6, 6 * 8, 1),
1069 MIPS64_SD(7, 7 * 8, 1),
1070 MIPS64_SD(8, 8 * 8, 1),
1071 MIPS64_SD(9, 9 * 8, 1),
1072 MIPS64_SD(10, 10 * 8, 1),
1073 MIPS64_SD(11, 11 * 8, 1),
1074 MIPS64_SD(12, 12 * 8, 1),
1075 MIPS64_SD(13, 13 * 8, 1),
1076 MIPS64_SD(14, 14 * 8, 1),
1077 MIPS64_SD(16, 16 * 8, 1),
1078 MIPS64_SD(17, 17 * 8, 1),
1079 MIPS64_SD(18, 18 * 8, 1),
1080 MIPS64_SD(19, 19 * 8, 1),
1081 MIPS64_SD(20, 20 * 8, 1),
1082 MIPS64_SD(21, 21 * 8, 1),
1083 MIPS64_SD(22, 22 * 8, 1),
1084 MIPS64_SD(23, 23 * 8, 1),
1085 MIPS64_SD(24, 24 * 8, 1),
1086 MIPS64_SD(25, 25 * 8, 1),
1087 MIPS64_SD(26, 26 * 8, 1),
1088 MIPS64_SD(27, 27 * 8, 1),
1089 MIPS64_SD(28, 28 * 8, 1),
1090 MIPS64_SD(29, 29 * 8, 1),
1091 MIPS64_SD(30, 30 * 8, 1),
1092 MIPS64_SD(31, 31 * 8, 1),
1093 MIPS64_MFLO(2),
1094 MIPS64_SD(2, 32 * 8, 1),
1095 MIPS64_MFHI(2),
1096 MIPS64_SD(2, 33 * 8, 1),
1097 MIPS64_DMFC0(2, MIPS64_C0_DEPC, 0),
1098 MIPS64_SD(2, MIPS64_NUM_CORE_REGS * 8, 1),
1099 MIPS64_DMFC0(2, MIPS64_C0_RANDOM, 0),
1100 MIPS64_SD(2, (MIPS64_NUM_CORE_REGS + 1) * 8, 1),
1101 MIPS64_DMFC0(2, MIPS64_C0_ENTRYLO0, 0),
1102 MIPS64_SD(2, (MIPS64_NUM_CORE_REGS + 2) * 8, 1),
1103 MIPS64_DMFC0(2, MIPS64_C0_ENTRYLO1, 0),
1104 MIPS64_SD(2, (MIPS64_NUM_CORE_REGS + 3) * 8, 1),
1105 MIPS64_DMFC0(2, MIPS64_C0_CONTEXT, 0),
1106 MIPS64_SD(2, (MIPS64_NUM_CORE_REGS + 4) * 8, 1),
1107 MIPS64_MFC0(2, MIPS64_C0_PAGEMASK, 0),
1108 MIPS64_SD(2, (MIPS64_NUM_CORE_REGS + 5) * 8, 1),
1109 MIPS64_MFC0(2, MIPS64_C0_WIRED, 0),
1110 MIPS64_SD(2, (MIPS64_NUM_CORE_REGS + 6) * 8, 1),
1111 MIPS64_DMFC0(2, MIPS64_C0_BADVADDR, 0),
1112 MIPS64_SD(2, (MIPS64_NUM_CORE_REGS + 7) * 8, 1),
1113 MIPS64_MFC0(2, MIPS64_C0_COUNT, 0),
1114 MIPS64_SD(2, (MIPS64_NUM_CORE_REGS + 8) * 8, 1),
1115 MIPS64_DMFC0(2, MIPS64_C0_ENTRYHI, 0),
1116 MIPS64_SD(2, (MIPS64_NUM_CORE_REGS + 9) * 8, 1),
1117 MIPS64_MFC0(2, MIPS64_C0_COMPARE, 0),
1118 MIPS64_SD(2, (MIPS64_NUM_CORE_REGS + 10) * 8, 1),
1119 MIPS64_MFC0(2, MIPS64_C0_STATUS, 0),
1120 MIPS64_SD(2, (MIPS64_NUM_CORE_REGS + 11) * 8, 1),
1121 MIPS64_MFC0(2, MIPS64_C0_CAUSE, 0),
1122 MIPS64_SD(2, (MIPS64_NUM_CORE_REGS + 12) * 8, 1),
1123 MIPS64_DMFC0(2, MIPS64_C0_EPC, 0),
1124 MIPS64_SD(2, (MIPS64_NUM_CORE_REGS + 13) * 8, 1),
1125 MIPS64_MFC0(2, MIPS64_C0_PRID, 0),
1126 MIPS64_SD(2, (MIPS64_NUM_CORE_REGS + 14) * 8, 1),
1127 MIPS64_MFC0(2, MIPS64_C0_CONFIG, 0),
1128 MIPS64_SD(2, (MIPS64_NUM_CORE_REGS + 15) * 8, 1),
1129 MIPS64_MFC0(2, MIPS64_C0_LLA, 0),
1130 MIPS64_SD(2, (MIPS64_NUM_CORE_REGS + 16) * 8, 1),
1131 MIPS64_DMFC0(2, MIPS64_C0_XCONTEXT, 1),
1132 MIPS64_SD(2, (MIPS64_NUM_CORE_REGS + 21) * 8, 1),
1133 MIPS64_MFC0(2, MIPS64_C0_MEMCTRL, 0),
1134 MIPS64_SD(2, (MIPS64_NUM_CORE_REGS + 22) * 8, 1),
1135 MIPS64_MFC0(2, MIPS64_C0_DEBUG, 0),
1136 MIPS64_SD(2, (MIPS64_NUM_CORE_REGS + 23) * 8, 1),
1137 MIPS64_MFC0(2, MIPS64_C0_PERFCOUNT, 0),
1138 MIPS64_SD(2, (MIPS64_NUM_CORE_REGS + 24) * 8, 1),
1139 MIPS64_MFC0(2, MIPS64_C0_PERFCOUNT, 1),
1140 MIPS64_SD(2, (MIPS64_NUM_CORE_REGS + 25) * 8, 1),
1141 MIPS64_MFC0(2, MIPS64_C0_PERFCOUNT, 2),
1142 MIPS64_SD(2, (MIPS64_NUM_CORE_REGS + 26) * 8, 1),
1143 MIPS64_MFC0(2, MIPS64_C0_PERFCOUNT, 3),
1144 MIPS64_SD(2, (MIPS64_NUM_CORE_REGS + 27) * 8, 1),
1145 MIPS64_MFC0(2, MIPS64_C0_ECC, 0),
1146 MIPS64_SD(2, (MIPS64_NUM_CORE_REGS + 28) * 8, 1),
1147 MIPS64_MFC0(2, MIPS64_C0_CACHERR, 0),
1148 MIPS64_SD(2, (MIPS64_NUM_CORE_REGS + 29) * 8, 1),
1149 MIPS64_MFC0(2, MIPS64_C0_TAGLO, 0),
1150 MIPS64_SD(2, (MIPS64_NUM_CORE_REGS + 30) * 8, 1),
1151 MIPS64_MFC0(2, MIPS64_C0_TAGHI, 0),
1152 MIPS64_SD(2, (MIPS64_NUM_CORE_REGS + 31) * 8, 1),
1153 MIPS64_DMFC0(2, MIPS64_C0_DATAHI, 0),
1154 MIPS64_SD(2, (MIPS64_NUM_CORE_REGS + 32) * 8, 1),
1155 MIPS64_DMFC0(2, MIPS64_C0_EEPC, 0),
1156 MIPS64_SD(2, (MIPS64_NUM_CORE_REGS + 33) * 8, 1),
1157 /* check if FPU is enabled, */
1158 MIPS64_MFC0(2, MIPS64_C0_STATUS, 0),
1159 MIPS64_SRL(2, 2, 29),
1160 MIPS64_ANDI(2, 2, 1),
1161 /* skip FPU registers dump if not */
1162 MIPS64_BEQ(0, 2, 77),
1163 MIPS64_NOP,
1164 MIPS64_CFC1(2, MIPS64_C1_FIR, 0),
1165 MIPS64_SD(2, (MIPS64_NUM_CORE_C0_REGS + 33) * 8, 1),
1166 MIPS64_CFC1(2, MIPS64_C1_FCSR, 0),
1167 MIPS64_SD(2, (MIPS64_NUM_CORE_C0_REGS + 32) * 8, 1),
1168 MIPS64_CFC1(2, MIPS64_C1_FCONFIG, 0),
1169 MIPS64_SD(2, (MIPS64_NUM_CORE_C0_REGS + 34) * 8, 1),
1170 MIPS64_CFC1(2, MIPS64_C1_FCCR, 0),
1171 MIPS64_SD(2, (MIPS64_NUM_CORE_C0_REGS + 35) * 8, 1),
1172 MIPS64_CFC1(2, MIPS64_C1_FEXR, 0),
1173 MIPS64_SD(2, (MIPS64_NUM_CORE_C0_REGS + 36) * 8, 1),
1174 MIPS64_CFC1(2, MIPS64_C1_FENR, 0),
1175 MIPS64_SD(2, (MIPS64_NUM_CORE_C0_REGS + 37) * 8, 1),
1176 MIPS64_DMFC1(2, 0, 0),
1177 MIPS64_SD(2, (MIPS64_NUM_CORE_C0_REGS + 0) * 8, 1),
1178 MIPS64_DMFC1(2, 1, 0),
1179 MIPS64_SD(2, (MIPS64_NUM_CORE_C0_REGS + 1) * 8, 1),
1180 MIPS64_DMFC1(2, 2, 0),
1181 MIPS64_SD(2, (MIPS64_NUM_CORE_C0_REGS + 2) * 8, 1),
1182 MIPS64_DMFC1(2, 3, 0),
1183 MIPS64_SD(2, (MIPS64_NUM_CORE_C0_REGS + 3) * 8, 1),
1184 MIPS64_DMFC1(2, 4, 0),
1185 MIPS64_SD(2, (MIPS64_NUM_CORE_C0_REGS + 4) * 8, 1),
1186 MIPS64_DMFC1(2, 5, 0),
1187 MIPS64_SD(2, (MIPS64_NUM_CORE_C0_REGS + 5) * 8, 1),
1188 MIPS64_DMFC1(2, 6, 0),
1189 MIPS64_SD(2, (MIPS64_NUM_CORE_C0_REGS + 6) * 8, 1),
1190 MIPS64_DMFC1(2, 7, 0),
1191 MIPS64_SD(2, (MIPS64_NUM_CORE_C0_REGS + 7) * 8, 1),
1192 MIPS64_DMFC1(2, 8, 0),
1193 MIPS64_SD(2, (MIPS64_NUM_CORE_C0_REGS + 8) * 8, 1),
1194 MIPS64_DMFC1(2, 9, 0),
1195 MIPS64_SD(2, (MIPS64_NUM_CORE_C0_REGS + 9) * 8, 1),
1196 MIPS64_DMFC1(2, 10, 0),
1197 MIPS64_SD(2, (MIPS64_NUM_CORE_C0_REGS + 10) * 8, 1),
1198 MIPS64_DMFC1(2, 11, 0),
1199 MIPS64_SD(2, (MIPS64_NUM_CORE_C0_REGS + 11) * 8, 1),
1200 MIPS64_DMFC1(2, 12, 0),
1201 MIPS64_SD(2, (MIPS64_NUM_CORE_C0_REGS + 12) * 8, 1),
1202 MIPS64_DMFC1(2, 13, 0),
1203 MIPS64_SD(2, (MIPS64_NUM_CORE_C0_REGS + 13) * 8, 1),
1204 MIPS64_DMFC1(2, 14, 0),
1205 MIPS64_SD(2, (MIPS64_NUM_CORE_C0_REGS + 14) * 8, 1),
1206 MIPS64_DMFC1(2, 15, 0),
1207 MIPS64_SD(2, (MIPS64_NUM_CORE_C0_REGS + 15) * 8, 1),
1208 MIPS64_DMFC1(2, 16, 0),
1209 MIPS64_SD(2, (MIPS64_NUM_CORE_C0_REGS + 16) * 8, 1),
1210 MIPS64_DMFC1(2, 17, 0),
1211 MIPS64_SD(2, (MIPS64_NUM_CORE_C0_REGS + 17) * 8, 1),
1212 MIPS64_DMFC1(2, 18, 0),
1213 MIPS64_SD(2, (MIPS64_NUM_CORE_C0_REGS + 18) * 8, 1),
1214 MIPS64_DMFC1(2, 19, 0),
1215 MIPS64_SD(2, (MIPS64_NUM_CORE_C0_REGS + 19) * 8, 1),
1216 MIPS64_DMFC1(2, 20, 0),
1217 MIPS64_SD(2, (MIPS64_NUM_CORE_C0_REGS + 20) * 8, 1),
1218 MIPS64_DMFC1(2, 21, 0),
1219 MIPS64_SD(2, (MIPS64_NUM_CORE_C0_REGS + 21) * 8, 1),
1220 MIPS64_DMFC1(2, 22, 0),
1221 MIPS64_SD(2, (MIPS64_NUM_CORE_C0_REGS + 22) * 8, 1),
1222 MIPS64_DMFC1(2, 23, 0),
1223 MIPS64_SD(2, (MIPS64_NUM_CORE_C0_REGS + 23) * 8, 1),
1224 MIPS64_DMFC1(2, 24, 0),
1225 MIPS64_SD(2, (MIPS64_NUM_CORE_C0_REGS + 24) * 8, 1),
1226 MIPS64_DMFC1(2, 25, 0),
1227 MIPS64_SD(2, (MIPS64_NUM_CORE_C0_REGS + 25) * 8, 1),
1228 MIPS64_DMFC1(2, 26, 0),
1229 MIPS64_SD(2, (MIPS64_NUM_CORE_C0_REGS + 26) * 8, 1),
1230 MIPS64_DMFC1(2, 27, 0),
1231 MIPS64_SD(2, (MIPS64_NUM_CORE_C0_REGS + 27) * 8, 1),
1232 MIPS64_DMFC1(2, 28, 0),
1233 MIPS64_SD(2, (MIPS64_NUM_CORE_C0_REGS + 28) * 8, 1),
1234 MIPS64_DMFC1(2, 29, 0),
1235 MIPS64_SD(2, (MIPS64_NUM_CORE_C0_REGS + 29) * 8, 1),
1236 MIPS64_DMFC1(2, 30, 0),
1237 MIPS64_SD(2, (MIPS64_NUM_CORE_C0_REGS + 30) * 8, 1),
1238 MIPS64_DMFC1(2, 31, 0),
1239 MIPS64_SD(2, (MIPS64_NUM_CORE_C0_REGS + 31) * 8, 1),
1240 MIPS64_LD(2, 0, 15),
1241 MIPS64_LD(1, 0, 15),
1242 MIPS64_SYNC,
1243 /* b start */
1244 MIPS64_B(NEG16(192)),
1245 /* move COP0 DeSave to $15 */
1246 MIPS64_DMFC0(15, 31, 0),
1247 MIPS64_NOP,
1248 MIPS64_NOP,
1249 MIPS64_NOP,
1250 MIPS64_NOP,
1251 MIPS64_NOP,
1252 MIPS64_NOP,
1253 MIPS64_NOP,
1254 MIPS64_NOP,
1255 };
1256
1257 LOG_DEBUG("enter mips64_pracc_exec");
1258 return mips64_pracc_exec(ejtag_info, ARRAY_SIZE(code), code,
1259 0, NULL, MIPS64_NUM_REGS, regs);
1260 }
1261
1262 /* fastdata upload/download requires an initialized working area
1263 * to load the download code; it should not be called otherwise
1264 * fetch order from the fastdata area
1265 * 1. start addr
1266 * 2. end addr
1267 * 3. data ...
1268 */
mips64_pracc_fastdata_xfer(struct mips_ejtag * ejtag_info,struct working_area * source,bool write_t,uint64_t addr,unsigned count,uint64_t * buf)1269 int mips64_pracc_fastdata_xfer(struct mips_ejtag *ejtag_info,
1270 struct working_area *source,
1271 bool write_t, uint64_t addr,
1272 unsigned count, uint64_t *buf)
1273 {
1274 uint32_t handler_code[] = {
1275 /* caution when editing, table is modified below */
1276 /* r15 points to the start of this code */
1277 MIPS64_SD(8, MIPS64_FASTDATA_HANDLER_SIZE - 8, 15),
1278 MIPS64_SD(9, MIPS64_FASTDATA_HANDLER_SIZE - 8 * 2, 15),
1279 MIPS64_SD(10, MIPS64_FASTDATA_HANDLER_SIZE - 8 * 3, 15),
1280 MIPS64_SD(11, MIPS64_FASTDATA_HANDLER_SIZE - 8 * 4, 15),
1281 /* start of fastdata area in t0 */
1282 MIPS64_LUI(8, UPPER16(MIPS64_PRACC_FASTDATA_AREA)),
1283 MIPS64_ORI(8, 8, LOWER16(MIPS64_PRACC_FASTDATA_AREA)),
1284 /* start addr in t1 */
1285 MIPS64_LD(9, 0, 8),
1286 /* end addr to t2 */
1287 MIPS64_LD(10, 0, 8),
1288
1289 /* loop: */
1290 /* lw t3,[t8 | r9] */
1291 /* 8 */ MIPS64_LD(11, 0, 0),
1292 /* sw t3,[r9 | r8] */
1293 /* 9 */ MIPS64_SD(11, 0, 0),
1294 /* bne $t2,t1,loop */
1295 MIPS64_BNE(10, 9, NEG16(3)),
1296 /* addi t1,t1,4 */
1297 MIPS64_DADDIU(9, 9, 8),
1298
1299 MIPS64_LD(8, MIPS64_FASTDATA_HANDLER_SIZE - 8, 15),
1300 MIPS64_LD(9, MIPS64_FASTDATA_HANDLER_SIZE - 8 * 2, 15),
1301 MIPS64_LD(10, MIPS64_FASTDATA_HANDLER_SIZE - 8 * 3, 15),
1302 MIPS64_LD(11, MIPS64_FASTDATA_HANDLER_SIZE - 8 * 4, 15),
1303
1304 MIPS64_LUI(15, UPPER16(MIPS64_PRACC_TEXT)),
1305 MIPS64_ORI(15, 15, LOWER16(MIPS64_PRACC_TEXT)),
1306 /* jr start */
1307 MIPS64_JR(15),
1308 /* move COP0 DeSave to $15 */
1309 MIPS64_DMFC0(15, 31, 0),
1310 };
1311
1312 uint32_t jmp_code[] = {
1313 /* addr of working area added below */
1314 /* 0 */ MIPS64_LUI(15, 0),
1315 /* addr of working area added below */
1316 /* 1 */ MIPS64_ORI(15, 15, 0),
1317 /* jump to ram program */
1318 MIPS64_JR(15),
1319 MIPS64_NOP,
1320 };
1321
1322 int retval;
1323 unsigned i;
1324 uint32_t ejtag_ctrl, address32;
1325 uint64_t address, val;
1326
1327 if (source->size < MIPS64_FASTDATA_HANDLER_SIZE)
1328 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
1329
1330 if (write_t) {
1331 /* load data from probe at fastdata area */
1332 handler_code[8] = MIPS64_LD(11, 0, 8);
1333 /* store data to RAM @ r9 */
1334 handler_code[9] = MIPS64_SD(11, 0, 9);
1335 } else {
1336 /* load data from RAM @ r9 */
1337 handler_code[8] = MIPS64_LD(11, 0, 9);
1338 /* store data to probe at fastdata area */
1339 handler_code[9] = MIPS64_SD(11, 0, 8);
1340 }
1341
1342 /* write program into RAM */
1343 if (write_t != ejtag_info->fast_access_save) {
1344 mips64_pracc_write_mem(ejtag_info, source->address, 4,
1345 ARRAY_SIZE(handler_code), handler_code);
1346 /* save previous operation to speed to any consecutive read/writes */
1347 ejtag_info->fast_access_save = write_t;
1348 }
1349
1350 LOG_DEBUG("%s using " TARGET_ADDR_FMT " for write handler", __func__,
1351 source->address);
1352 LOG_DEBUG("daddiu: %08" PRIx32, handler_code[11]);
1353
1354 jmp_code[0] |= UPPER16(source->address);
1355 jmp_code[1] |= LOWER16(source->address);
1356 mips64_pracc_exec(ejtag_info,
1357 ARRAY_SIZE(jmp_code), jmp_code,
1358 0, NULL, 0, NULL);
1359
1360 /* next fetch to dmseg should be in FASTDATA_AREA, check */
1361 address = 0;
1362
1363 mips_ejtag_set_instr(ejtag_info, EJTAG_INST_ADDRESS);
1364 retval = mips_ejtag_drscan_32(ejtag_info, &address32);
1365 if (retval != ERROR_OK)
1366 return retval;
1367 address = 0xffffffffff200000ull | address32;
1368 if ((address & ~7ull) != MIPS64_PRACC_FASTDATA_AREA) {
1369 LOG_ERROR("! @MIPS64_PRACC_FASTDATA_AREA (" TARGET_ADDR_FMT ")", address);
1370 return ERROR_FAIL;
1371 }
1372 /* Send the load start address */
1373 val = addr;
1374 LOG_DEBUG("start: " TARGET_ADDR_FMT, val);
1375 mips_ejtag_set_instr(ejtag_info, EJTAG_INST_FASTDATA);
1376 mips64_ejtag_fastdata_scan(ejtag_info, 1, &val);
1377
1378 retval = wait_for_pracc_rw(ejtag_info, &ejtag_ctrl);
1379 if (retval != ERROR_OK)
1380 return retval;
1381
1382 /* Send the load end address */
1383 val = addr + (count - 1) * 8;
1384 LOG_DEBUG("stop: " TARGET_ADDR_FMT, val);
1385 mips_ejtag_set_instr(ejtag_info, EJTAG_INST_FASTDATA);
1386 mips64_ejtag_fastdata_scan(ejtag_info, 1, &val);
1387
1388 /* like in legacy code */
1389 unsigned num_clocks = 0;
1390 if (ejtag_info->mode != 0)
1391 num_clocks = ((uint64_t)(ejtag_info->scan_delay) * jtag_get_speed_khz() + 500000) / 1000000;
1392 LOG_DEBUG("num_clocks=%d", num_clocks);
1393 for (i = 0; i < count; i++) {
1394 jtag_add_clocks(num_clocks);
1395 retval = mips64_ejtag_fastdata_scan(ejtag_info, write_t, buf++);
1396 if (retval != ERROR_OK) {
1397 LOG_ERROR("mips64_ejtag_fastdata_scan failed");
1398 return retval;
1399 }
1400 }
1401
1402 retval = jtag_execute_queue();
1403 if (retval != ERROR_OK) {
1404 LOG_ERROR("jtag_execute_queue failed");
1405 return retval;
1406 }
1407
1408 retval = wait_for_pracc_rw(ejtag_info, &ejtag_ctrl);
1409 if (retval != ERROR_OK) {
1410 LOG_ERROR("wait_for_pracc_rw failed");
1411 return retval;
1412 }
1413
1414 address = 0;
1415 mips_ejtag_set_instr(ejtag_info, EJTAG_INST_ADDRESS);
1416 retval = mips_ejtag_drscan_32(ejtag_info, &address32);
1417 if (retval != ERROR_OK) {
1418 LOG_ERROR("mips_ejtag_drscan_32 failed");
1419 return retval;
1420 }
1421
1422 address = 0xffffffffff200000ull | address32;
1423 if ((address & ~7ull) != MIPS64_PRACC_TEXT)
1424 LOG_ERROR("mini program did not return to start");
1425
1426 return retval;
1427 }
1428