mips32, add realloc code
[openocd.git] / src / target / mips32_pracc.c
1 /***************************************************************************
2 * Copyright (C) 2008 by Spencer Oliver *
3 * spen@spen-soft.co.uk *
4 * *
5 * Copyright (C) 2008 by David T.L. Wong *
6 * *
7 * Copyright (C) 2009 by David N. Claffey <dnclaffey@gmail.com> *
8 * *
9 * Copyright (C) 2011 by Drasko DRASKOVIC *
10 * drasko.draskovic@gmail.com *
11 * *
12 * This program is free software; you can redistribute it and/or modify *
13 * it under the terms of the GNU General Public License as published by *
14 * the Free Software Foundation; either version 2 of the License, or *
15 * (at your option) any later version. *
16 * *
17 * This program is distributed in the hope that it will be useful, *
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
20 * GNU General Public License for more details. *
21 * *
22 * You should have received a copy of the GNU General Public License *
23 * along with this program. If not, see <http://www.gnu.org/licenses/>. *
24 ***************************************************************************/
25
26 /*
27 * This version has optimized assembly routines for 32 bit operations:
28 * - read word
29 * - write word
30 * - write array of words
31 *
32 * One thing to be aware of is that the MIPS32 cpu will execute the
33 * instruction after a branch instruction (one delay slot).
34 *
35 * For example:
36 * LW $2, ($5 +10)
37 * B foo
38 * LW $1, ($2 +100)
39 *
40 * The LW $1, ($2 +100) instruction is also executed. If this is
41 * not wanted a NOP can be inserted:
42 *
43 * LW $2, ($5 +10)
44 * B foo
45 * NOP
46 * LW $1, ($2 +100)
47 *
48 * or the code can be changed to:
49 *
50 * B foo
51 * LW $2, ($5 +10)
52 * LW $1, ($2 +100)
53 *
54 * The original code contained NOPs. I have removed these and moved
55 * the branches.
56 *
57 * These changes result in a 35% speed increase when programming an
58 * external flash.
59 *
60 * More improvement could be gained if the registers do no need
61 * to be preserved but in that case the routines should be aware
62 * OpenOCD is used as a flash programmer or as a debug tool.
63 *
64 * Nico Coesel
65 */
66
67 #ifdef HAVE_CONFIG_H
68 #include "config.h"
69 #endif
70
71 #include <helper/time_support.h>
72
73 #include "mips32.h"
74 #include "mips32_pracc.h"
75
76 static int wait_for_pracc_rw(struct mips_ejtag *ejtag_info)
77 {
78 int64_t then = timeval_ms();
79
80 /* wait for the PrAcc to become "1" */
81 mips_ejtag_set_instr(ejtag_info, EJTAG_INST_CONTROL);
82
83 while (1) {
84 ejtag_info->pa_ctrl = ejtag_info->ejtag_ctrl;
85 int retval = mips_ejtag_drscan_32(ejtag_info, &ejtag_info->pa_ctrl);
86 if (retval != ERROR_OK)
87 return retval;
88
89 if (ejtag_info->pa_ctrl & EJTAG_CTRL_PRACC)
90 break;
91
92 int64_t timeout = timeval_ms() - then;
93 if (timeout > 1000) {
94 LOG_DEBUG("DEBUGMODULE: No memory access in progress!");
95 return ERROR_JTAG_DEVICE_ERROR;
96 }
97 }
98
99 return ERROR_OK;
100 }
101
102 /* Shift in control and address for a new processor access, save them in ejtag_info */
103 static int mips32_pracc_read_ctrl_addr(struct mips_ejtag *ejtag_info)
104 {
105 int retval = wait_for_pracc_rw(ejtag_info);
106 if (retval != ERROR_OK)
107 return retval;
108
109 mips_ejtag_set_instr(ejtag_info, EJTAG_INST_ADDRESS);
110
111 ejtag_info->pa_addr = 0;
112 return mips_ejtag_drscan_32(ejtag_info, &ejtag_info->pa_addr);
113 }
114
115 /* Finish processor access */
116 static void mips32_pracc_finish(struct mips_ejtag *ejtag_info)
117 {
118 uint32_t ctrl = ejtag_info->ejtag_ctrl & ~EJTAG_CTRL_PRACC;
119 mips_ejtag_set_instr(ejtag_info, EJTAG_INST_CONTROL);
120 mips_ejtag_drscan_32_out(ejtag_info, ctrl);
121 }
122
123 int mips32_pracc_clean_text_jump(struct mips_ejtag *ejtag_info)
124 {
125 uint32_t jt_code = MIPS32_J((0x0FFFFFFF & MIPS32_PRACC_TEXT) >> 2);
126
127 /* do 3 0/nops to clean pipeline before a jump to pracc text, NOP in delay slot */
128 for (int i = 0; i != 5; i++) {
129 /* Wait for pracc */
130 int retval = wait_for_pracc_rw(ejtag_info);
131 if (retval != ERROR_OK)
132 return retval;
133
134 /* Data or instruction out */
135 mips_ejtag_set_instr(ejtag_info, EJTAG_INST_DATA);
136 uint32_t data = (i == 3) ? jt_code : MIPS32_NOP;
137 mips_ejtag_drscan_32_out(ejtag_info, data);
138
139 /* finish pa */
140 mips32_pracc_finish(ejtag_info);
141 }
142
143 if (ejtag_info->mode != 0) /* async mode support only for MIPS ... */
144 return ERROR_OK;
145
146 for (int i = 0; i != 2; i++) {
147 int retval = mips32_pracc_read_ctrl_addr(ejtag_info);
148 if (retval != ERROR_OK)
149 return retval;
150
151 if (ejtag_info->pa_addr != MIPS32_PRACC_TEXT) { /* LEXRA/BMIPS ?, shift out another NOP, max 2 */
152 mips_ejtag_set_instr(ejtag_info, EJTAG_INST_DATA);
153 mips_ejtag_drscan_32_out(ejtag_info, MIPS32_NOP);
154 mips32_pracc_finish(ejtag_info);
155 } else
156 break;
157 }
158
159 return ERROR_OK;
160 }
161
162 int mips32_pracc_exec(struct mips_ejtag *ejtag_info, struct pracc_queue_info *ctx, uint32_t *param_out)
163 {
164 int code_count = 0;
165 int store_pending = 0; /* increases with every store instruction at dmseg, decreases with every store pa */
166 uint32_t max_store_addr = 0; /* for store pa address testing */
167 bool restart = 0; /* restarting control */
168 int restart_count = 0;
169 uint32_t instr = 0;
170 bool final_check = 0; /* set to 1 if in final checks after function code shifted out */
171 bool pass = 0; /* to check the pass through pracc text after function code sent */
172 int retval;
173
174 while (1) {
175 if (restart) {
176 if (restart_count < 3) { /* max 3 restarts allowed */
177 retval = mips32_pracc_clean_text_jump(ejtag_info);
178 if (retval != ERROR_OK)
179 return retval;
180 } else
181 return ERROR_JTAG_DEVICE_ERROR;
182 restart_count++;
183 restart = 0;
184 code_count = 0;
185 LOG_DEBUG("restarting code");
186 }
187
188 retval = mips32_pracc_read_ctrl_addr(ejtag_info); /* update current pa info: control and address */
189 if (retval != ERROR_OK)
190 return retval;
191
192 /* Check for read or write access */
193 if (ejtag_info->pa_ctrl & EJTAG_CTRL_PRNW) { /* write/store access */
194 /* Check for pending store from a previous store instruction at dmseg */
195 if (store_pending == 0) {
196 LOG_DEBUG("unexpected write at address %" PRIx32, ejtag_info->pa_addr);
197 if (code_count < 2) { /* allow for restart */
198 restart = 1;
199 continue;
200 } else
201 return ERROR_JTAG_DEVICE_ERROR;
202 } else {
203 /* check address */
204 if (ejtag_info->pa_addr < MIPS32_PRACC_PARAM_OUT || ejtag_info->pa_addr > max_store_addr) {
205
206 LOG_DEBUG("writing at unexpected address %" PRIx32, ejtag_info->pa_addr);
207 return ERROR_JTAG_DEVICE_ERROR;
208 }
209 }
210 /* read data */
211 uint32_t data = 0;
212 mips_ejtag_set_instr(ejtag_info, EJTAG_INST_DATA);
213 retval = mips_ejtag_drscan_32(ejtag_info, &data);
214 if (retval != ERROR_OK)
215 return retval;
216
217 /* store data at param out, address based offset */
218 param_out[(ejtag_info->pa_addr - MIPS32_PRACC_PARAM_OUT) / 4] = data;
219 store_pending--;
220
221 } else { /* read/fetch access */
222 if (!final_check) { /* executing function code */
223 /* check address */
224 if (ejtag_info->pa_addr != (MIPS32_PRACC_TEXT + code_count * 4)) {
225 LOG_DEBUG("reading at unexpected address %" PRIx32 ", expected %x",
226 ejtag_info->pa_addr, MIPS32_PRACC_TEXT + code_count * 4);
227
228 /* restart code execution only in some cases */
229 if (code_count == 1 && ejtag_info->pa_addr == MIPS32_PRACC_TEXT && restart_count == 0) {
230 LOG_DEBUG("restarting, without clean jump");
231 restart_count++;
232 code_count = 0;
233 continue;
234 } else if (code_count < 2) {
235 restart = 1;
236 continue;
237 }
238 return ERROR_JTAG_DEVICE_ERROR;
239 }
240 /* check for store instruction at dmseg */
241 uint32_t store_addr = ctx->pracc_list[code_count].addr;
242 if (store_addr != 0) {
243 if (store_addr > max_store_addr)
244 max_store_addr = store_addr;
245 store_pending++;
246 }
247
248 instr = ctx->pracc_list[code_count++].instr;
249 if (code_count == ctx->code_count) /* last instruction, start final check */
250 final_check = 1;
251
252 } else { /* final check after function code shifted out */
253 /* check address */
254 if (ejtag_info->pa_addr == MIPS32_PRACC_TEXT) {
255 if (!pass) { /* first pass through pracc text */
256 if (store_pending == 0) /* done, normal exit */
257 return ERROR_OK;
258 pass = 1; /* pracc text passed */
259 code_count = 0; /* restart code count */
260 } else {
261 LOG_DEBUG("unexpected second pass through pracc text");
262 return ERROR_JTAG_DEVICE_ERROR;
263 }
264 } else {
265 if (ejtag_info->pa_addr != (MIPS32_PRACC_TEXT + code_count * 4)) {
266 LOG_DEBUG("unexpected read address in final check: %" PRIx32 ", expected: %x",
267 ejtag_info->pa_addr, MIPS32_PRACC_TEXT + code_count * 4);
268 return ERROR_JTAG_DEVICE_ERROR;
269 }
270 }
271 if (!pass) {
272 if ((code_count - ctx->code_count) > 1) { /* allow max 2 instruction delay slot */
273 LOG_DEBUG("failed to jump back to pracc text");
274 return ERROR_JTAG_DEVICE_ERROR;
275 }
276 } else
277 if (code_count > 10) { /* enough, abandone */
278 LOG_DEBUG("execution abandoned, store pending: %d", store_pending);
279 return ERROR_JTAG_DEVICE_ERROR;
280 }
281 instr = MIPS32_NOP; /* shift out NOPs instructions */
282 code_count++;
283 }
284
285 /* Send instruction out */
286 mips_ejtag_set_instr(ejtag_info, EJTAG_INST_DATA);
287 mips_ejtag_drscan_32_out(ejtag_info, instr);
288 }
289 /* finish processor access, let the processor eat! */
290 mips32_pracc_finish(ejtag_info);
291
292 if (instr == MIPS32_DRET) /* after leaving debug mode nothing to do */
293 return jtag_execute_queue();
294
295 if (store_pending == 0 && pass) { /* store access done, but after passing pracc text */
296 LOG_DEBUG("warning: store access pass pracc text");
297 return ERROR_OK;
298 }
299 }
300 }
301
302 inline void pracc_queue_init(struct pracc_queue_info *ctx)
303 {
304 ctx->retval = ERROR_OK;
305 ctx->code_count = 0;
306 ctx->store_count = 0;
307 ctx->max_code = 0;
308 ctx->pracc_list = NULL;
309 }
310
311 void pracc_add(struct pracc_queue_info *ctx, uint32_t addr, uint32_t instr)
312 {
313 if (ctx->retval != ERROR_OK) /* On previous out of memory, return */
314 return;
315 if (ctx->code_count == ctx->max_code) {
316 void *p = realloc(ctx->pracc_list, sizeof(pa_list) * (ctx->max_code + PRACC_BLOCK));
317 if (p) {
318 ctx->max_code += PRACC_BLOCK;
319 ctx->pracc_list = p;
320 } else {
321 ctx->retval = ERROR_FAIL; /* Out of memory */
322 return;
323 }
324 }
325 ctx->pracc_list[ctx->code_count].instr = instr;
326 ctx->pracc_list[ctx->code_count++].addr = addr;
327 if (addr)
328 ctx->store_count++;
329 }
330
331 void pracc_add_li32(struct pracc_queue_info *ctx, uint32_t reg_num, uint32_t data, bool optimize)
332 {
333 if (LOWER16(data) == 0 && optimize)
334 pracc_add(ctx, 0, MIPS32_LUI(reg_num, UPPER16(data))); /* load only upper value */
335 else if (UPPER16(data) == 0 && optimize)
336 pracc_add(ctx, 0, MIPS32_ORI(reg_num, 0, LOWER16(data))); /* load only lower */
337 else {
338 pracc_add(ctx, 0, MIPS32_LUI(reg_num, UPPER16(data))); /* load upper and lower */
339 pracc_add(ctx, 0, MIPS32_ORI(reg_num, reg_num, LOWER16(data)));
340 }
341 }
342
343 inline void pracc_queue_free(struct pracc_queue_info *ctx)
344 {
345 if (ctx->pracc_list != NULL)
346 free(ctx->pracc_list);
347 }
348
349 int mips32_pracc_queue_exec(struct mips_ejtag *ejtag_info, struct pracc_queue_info *ctx, uint32_t *buf)
350 {
351 if (ctx->retval != ERROR_OK) {
352 LOG_ERROR("Out of memory");
353 return ERROR_FAIL;
354 }
355
356 if (ejtag_info->mode == 0)
357 return mips32_pracc_exec(ejtag_info, ctx, buf);
358
359 union scan_in {
360 uint8_t scan_96[12];
361 struct {
362 uint8_t ctrl[4];
363 uint8_t data[4];
364 uint8_t addr[4];
365 } scan_32;
366
367 } *scan_in = malloc(sizeof(union scan_in) * (ctx->code_count + ctx->store_count));
368 if (scan_in == NULL) {
369 LOG_ERROR("Out of memory");
370 return ERROR_FAIL;
371 }
372
373 unsigned num_clocks =
374 ((uint64_t)(ejtag_info->scan_delay) * jtag_get_speed_khz() + 500000) / 1000000;
375
376 uint32_t ejtag_ctrl = ejtag_info->ejtag_ctrl & ~EJTAG_CTRL_PRACC;
377 mips_ejtag_set_instr(ejtag_info, EJTAG_INST_ALL);
378
379 int scan_count = 0;
380 for (int i = 0; i != ctx->code_count; i++) {
381 jtag_add_clocks(num_clocks);
382 mips_ejtag_add_scan_96(ejtag_info, ejtag_ctrl, ctx->pracc_list[i].instr,
383 scan_in[scan_count++].scan_96);
384
385 /* Check store address from previous instruction, if not the first */
386 if (i > 0 && ctx->pracc_list[i - 1].addr) {
387 jtag_add_clocks(num_clocks);
388 mips_ejtag_add_scan_96(ejtag_info, ejtag_ctrl, 0, scan_in[scan_count++].scan_96);
389 }
390 }
391
392 int retval = jtag_execute_queue(); /* execute queued scans */
393 if (retval != ERROR_OK)
394 goto exit;
395
396 uint32_t fetch_addr = MIPS32_PRACC_TEXT; /* start address */
397 scan_count = 0;
398 for (int i = 0; i != ctx->code_count; i++) { /* verify every pracc access */
399 /* check pracc bit */
400 ejtag_ctrl = buf_get_u32(scan_in[scan_count].scan_32.ctrl, 0, 32);
401 uint32_t addr = buf_get_u32(scan_in[scan_count].scan_32.addr, 0, 32);
402 if (!(ejtag_ctrl & EJTAG_CTRL_PRACC)) {
403 LOG_ERROR("Error: access not pending count: %d", scan_count);
404 retval = ERROR_FAIL;
405 goto exit;
406 }
407 if (ejtag_ctrl & EJTAG_CTRL_PRNW) {
408 LOG_ERROR("Not a fetch/read access, count: %d", scan_count);
409 retval = ERROR_FAIL;
410 goto exit;
411 }
412 if (addr != fetch_addr) {
413 LOG_ERROR("Fetch addr mismatch, read: %" PRIx32 " expected: %" PRIx32 " count: %d",
414 addr, fetch_addr, scan_count);
415 retval = ERROR_FAIL;
416 goto exit;
417 }
418 fetch_addr += 4;
419 scan_count++;
420
421 /* check if previous intrucction is a store instruction at dmesg */
422 if (i > 0 && ctx->pracc_list[i - 1].addr) {
423 uint32_t store_addr = ctx->pracc_list[i - 1].addr;
424 ejtag_ctrl = buf_get_u32(scan_in[scan_count].scan_32.ctrl, 0, 32);
425 addr = buf_get_u32(scan_in[scan_count].scan_32.addr, 0, 32);
426
427 if (!(ejtag_ctrl & EJTAG_CTRL_PRNW)) {
428 LOG_ERROR("Not a store/write access, count: %d", scan_count);
429 retval = ERROR_FAIL;
430 goto exit;
431 }
432 if (addr != store_addr) {
433 LOG_ERROR("Store address mismatch, read: %" PRIx32 " expected: %" PRIx32 " count: %d",
434 addr, store_addr, scan_count);
435 retval = ERROR_FAIL;
436 goto exit;
437 }
438 int buf_index = (addr - MIPS32_PRACC_PARAM_OUT) / 4;
439 buf[buf_index] = buf_get_u32(scan_in[scan_count].scan_32.data, 0, 32);
440 scan_count++;
441 }
442 }
443 exit:
444 free(scan_in);
445 return retval;
446 }
447
448 int mips32_pracc_read_u32(struct mips_ejtag *ejtag_info, uint32_t addr, uint32_t *buf)
449 {
450 struct pracc_queue_info ctx;
451 pracc_queue_init(&ctx);
452
453 pracc_add(&ctx, 0, MIPS32_LUI(15, PRACC_UPPER_BASE_ADDR)); /* $15 = MIPS32_PRACC_BASE_ADDR */
454 pracc_add(&ctx, 0, MIPS32_LUI(8, UPPER16((addr + 0x8000)))); /* load $8 with modified upper address */
455 pracc_add(&ctx, 0, MIPS32_LW(8, LOWER16(addr), 8)); /* lw $8, LOWER16(addr)($8) */
456 pracc_add(&ctx, MIPS32_PRACC_PARAM_OUT,
457 MIPS32_SW(8, PRACC_OUT_OFFSET, 15)); /* sw $8,PRACC_OUT_OFFSET($15) */
458 pracc_add_li32(&ctx, 8, ejtag_info->reg8, 0); /* restore $8 */
459 pracc_add(&ctx, 0, MIPS32_B(NEG16(ctx.code_count + 1))); /* jump to start */
460 pracc_add(&ctx, 0, MIPS32_MFC0(15, 31, 0)); /* move COP0 DeSave to $15 */
461
462 ctx.retval = mips32_pracc_queue_exec(ejtag_info, &ctx, buf);
463 pracc_queue_free(&ctx);
464 return ctx.retval;
465 }
466
467 int mips32_pracc_read_mem(struct mips_ejtag *ejtag_info, uint32_t addr, int size, int count, void *buf)
468 {
469 if (count == 1 && size == 4)
470 return mips32_pracc_read_u32(ejtag_info, addr, (uint32_t *)buf);
471
472 uint32_t *data = NULL;
473 struct pracc_queue_info ctx;
474 pracc_queue_init(&ctx);
475
476 if (size != 4) {
477 data = malloc(256 * sizeof(uint32_t));
478 if (data == NULL) {
479 LOG_ERROR("Out of memory");
480 goto exit;
481 }
482 }
483
484 uint32_t *buf32 = buf;
485 uint16_t *buf16 = buf;
486 uint8_t *buf8 = buf;
487
488 while (count) {
489 ctx.code_count = 0;
490 ctx.store_count = 0;
491 int this_round_count = (count > 256) ? 256 : count;
492 uint32_t last_upper_base_addr = UPPER16((addr + 0x8000));
493
494 pracc_add(&ctx, 0, MIPS32_LUI(15, PRACC_UPPER_BASE_ADDR)); /* $15 = MIPS32_PRACC_BASE_ADDR */
495 pracc_add(&ctx, 0, MIPS32_LUI(9, last_upper_base_addr)); /* load the upper memory address in $9 */
496
497 for (int i = 0; i != this_round_count; i++) { /* Main code loop */
498 uint32_t upper_base_addr = UPPER16((addr + 0x8000));
499 if (last_upper_base_addr != upper_base_addr) { /* if needed, change upper address in $9 */
500 pracc_add(&ctx, 0, MIPS32_LUI(9, upper_base_addr));
501 last_upper_base_addr = upper_base_addr;
502 }
503
504 if (size == 4)
505 pracc_add(&ctx, 0, MIPS32_LW(8, LOWER16(addr), 9)); /* load from memory to $8 */
506 else if (size == 2)
507 pracc_add(&ctx, 0, MIPS32_LHU(8, LOWER16(addr), 9));
508 else
509 pracc_add(&ctx, 0, MIPS32_LBU(8, LOWER16(addr), 9));
510
511 pracc_add(&ctx, MIPS32_PRACC_PARAM_OUT + i * 4,
512 MIPS32_SW(8, PRACC_OUT_OFFSET + i * 4, 15)); /* store $8 at param out */
513 addr += size;
514 }
515 pracc_add_li32(&ctx, 8, ejtag_info->reg8, 0); /* restore $8 */
516 pracc_add_li32(&ctx, 9, ejtag_info->reg9, 0); /* restore $9 */
517
518 pracc_add(&ctx, 0, MIPS32_B(NEG16(ctx.code_count + 1))); /* jump to start */
519 pracc_add(&ctx, 0, MIPS32_MFC0(15, 31, 0)); /* restore $15 from DeSave */
520
521 if (size == 4) {
522 ctx.retval = mips32_pracc_queue_exec(ejtag_info, &ctx, buf32);
523 if (ctx.retval != ERROR_OK)
524 goto exit;
525 buf32 += this_round_count;
526 } else {
527 ctx.retval = mips32_pracc_queue_exec(ejtag_info, &ctx, data);
528 if (ctx.retval != ERROR_OK)
529 goto exit;
530
531 uint32_t *data_p = data;
532 for (int i = 0; i != this_round_count; i++) {
533 if (size == 2)
534 *buf16++ = *data_p++;
535 else
536 *buf8++ = *data_p++;
537 }
538 }
539 count -= this_round_count;
540 }
541 exit:
542 pracc_queue_free(&ctx);
543 if (data != NULL)
544 free(data);
545 return ctx.retval;
546 }
547
548 int mips32_cp0_read(struct mips_ejtag *ejtag_info, uint32_t *val, uint32_t cp0_reg, uint32_t cp0_sel)
549 {
550 struct pracc_queue_info ctx;
551 pracc_queue_init(&ctx);
552
553 pracc_add(&ctx, 0, MIPS32_LUI(15, PRACC_UPPER_BASE_ADDR)); /* $15 = MIPS32_PRACC_BASE_ADDR */
554 pracc_add(&ctx, 0, MIPS32_MFC0(8, cp0_reg, cp0_sel)); /* move cp0 reg / sel to $8 */
555 pracc_add(&ctx, MIPS32_PRACC_PARAM_OUT,
556 MIPS32_SW(8, PRACC_OUT_OFFSET, 15)); /* store $8 to pracc_out */
557 pracc_add(&ctx, 0, MIPS32_MFC0(15, 31, 0)); /* restore $15 from DeSave */
558 pracc_add(&ctx, 0, MIPS32_LUI(8, UPPER16(ejtag_info->reg8))); /* restore upper 16 bits of $8 */
559 pracc_add(&ctx, 0, MIPS32_B(NEG16(ctx.code_count + 1))); /* jump to start */
560 pracc_add(&ctx, 0, MIPS32_ORI(8, 8, LOWER16(ejtag_info->reg8))); /* restore lower 16 bits of $8 */
561
562 ctx.retval = mips32_pracc_queue_exec(ejtag_info, &ctx, val);
563 pracc_queue_free(&ctx);
564 return ctx.retval;
565 }
566
567 int mips32_cp0_write(struct mips_ejtag *ejtag_info, uint32_t val, uint32_t cp0_reg, uint32_t cp0_sel)
568 {
569 struct pracc_queue_info ctx;
570 pracc_queue_init(&ctx);
571
572 pracc_add_li32(&ctx, 15, val, 0); /* Load val to $15 */
573
574 pracc_add(&ctx, 0, MIPS32_MTC0(15, cp0_reg, cp0_sel)); /* write $15 to cp0 reg / sel */
575 pracc_add(&ctx, 0, MIPS32_B(NEG16(ctx.code_count + 1))); /* jump to start */
576 pracc_add(&ctx, 0, MIPS32_MFC0(15, 31, 0)); /* restore $15 from DeSave */
577
578 ctx.retval = mips32_pracc_queue_exec(ejtag_info, &ctx, NULL);
579 pracc_queue_free(&ctx);
580 return ctx.retval;
581 }
582
583 /**
584 * \b mips32_pracc_sync_cache
585 *
586 * Synchronize Caches to Make Instruction Writes Effective
587 * (ref. doc. MIPS32 Architecture For Programmers Volume II: The MIPS32 Instruction Set,
588 * Document Number: MD00086, Revision 2.00, June 9, 2003)
589 *
590 * When the instruction stream is written, the SYNCI instruction should be used
591 * in conjunction with other instructions to make the newly-written instructions effective.
592 *
593 * Explanation :
594 * A program that loads another program into memory is actually writing the D- side cache.
595 * The instructions it has loaded can't be executed until they reach the I-cache.
596 *
597 * After the instructions have been written, the loader should arrange
598 * to write back any containing D-cache line and invalidate any locations
599 * already in the I-cache.
600 *
601 * If the cache coherency attribute (CCA) is set to zero, it's a write through cache, there is no need
602 * to write back.
603 *
604 * In the latest MIPS32/64 CPUs, MIPS provides the synci instruction,
605 * which does the whole job for a cache-line-sized chunk of the memory you just loaded:
606 * That is, it arranges a D-cache write-back (if CCA = 3) and an I-cache invalidate.
607 *
608 * The line size is obtained with the rdhwr SYNCI_Step in release 2 or from cp0 config 1 register in release 1.
609 */
610 static int mips32_pracc_synchronize_cache(struct mips_ejtag *ejtag_info,
611 uint32_t start_addr, uint32_t end_addr, int cached, int rel)
612 {
613 struct pracc_queue_info ctx;
614 pracc_queue_init(&ctx);
615
616 /** Find cache line size in bytes */
617 uint32_t clsiz;
618 if (rel) { /* Release 2 (rel = 1) */
619 pracc_add(&ctx, 0, MIPS32_LUI(15, PRACC_UPPER_BASE_ADDR)); /* $15 = MIPS32_PRACC_BASE_ADDR */
620
621 pracc_add(&ctx, 0, MIPS32_RDHWR(8, MIPS32_SYNCI_STEP)); /* load synci_step value to $8 */
622
623 pracc_add(&ctx, MIPS32_PRACC_PARAM_OUT,
624 MIPS32_SW(8, PRACC_OUT_OFFSET, 15)); /* store $8 to pracc_out */
625
626 pracc_add_li32(&ctx, 8, ejtag_info->reg8, 0); /* restore $8 */
627
628 pracc_add(&ctx, 0, MIPS32_B(NEG16(ctx.code_count + 1))); /* jump to start */
629 pracc_add(&ctx, 0, MIPS32_MFC0(15, 31, 0)); /* move COP0 DeSave to $15 */
630
631 ctx.retval = mips32_pracc_queue_exec(ejtag_info, &ctx, &clsiz);
632 if (ctx.retval != ERROR_OK)
633 goto exit;
634
635 } else { /* Release 1 (rel = 0) */
636 uint32_t conf;
637 ctx.retval = mips32_cp0_read(ejtag_info, &conf, 16, 1);
638 if (ctx.retval != ERROR_OK)
639 goto exit;
640
641 uint32_t dl = (conf & MIPS32_CONFIG1_DL_MASK) >> MIPS32_CONFIG1_DL_SHIFT;
642
643 /* dl encoding : dl=1 => 4 bytes, dl=2 => 8 bytes, etc... max dl=6 => 128 bytes cache line size */
644 clsiz = 0x2 << dl;
645 if (dl == 0)
646 clsiz = 0;
647 }
648
649 if (clsiz == 0)
650 goto exit; /* Nothing to do */
651
652 /* make sure clsiz is power of 2 */
653 if (clsiz & (clsiz - 1)) {
654 LOG_DEBUG("clsiz must be power of 2");
655 ctx.retval = ERROR_FAIL;
656 goto exit;
657 }
658
659 /* make sure start_addr and end_addr have the same offset inside de cache line */
660 start_addr |= clsiz - 1;
661 end_addr |= clsiz - 1;
662
663 ctx.code_count = 0;
664 int count = 0;
665 uint32_t last_upper_base_addr = UPPER16((start_addr + 0x8000));
666
667 pracc_add(&ctx, 0, MIPS32_LUI(15, last_upper_base_addr)); /* load upper memory base address to $15 */
668
669 while (start_addr <= end_addr) { /* main loop */
670 uint32_t upper_base_addr = UPPER16((start_addr + 0x8000));
671 if (last_upper_base_addr != upper_base_addr) { /* if needed, change upper address in $15 */
672 pracc_add(&ctx, 0, MIPS32_LUI(15, upper_base_addr));
673 last_upper_base_addr = upper_base_addr;
674 }
675 if (rel)
676 pracc_add(&ctx, 0, MIPS32_SYNCI(LOWER16(start_addr), 15)); /* synci instruction, offset($15) */
677
678 else {
679 if (cached == 3)
680 pracc_add(&ctx, 0, MIPS32_CACHE(MIPS32_CACHE_D_HIT_WRITEBACK,
681 LOWER16(start_addr), 15)); /* cache Hit_Writeback_D, offset($15) */
682
683 pracc_add(&ctx, 0, MIPS32_CACHE(MIPS32_CACHE_I_HIT_INVALIDATE,
684 LOWER16(start_addr), 15)); /* cache Hit_Invalidate_I, offset($15) */
685 }
686 start_addr += clsiz;
687 count++;
688 if (count == 256 && start_addr <= end_addr) { /* more ?, then execute code list */
689 pracc_add(&ctx, 0, MIPS32_B(NEG16(ctx.code_count + 1))); /* jump to start */
690 pracc_add(&ctx, 0, MIPS32_NOP); /* nop in delay slot */
691
692 ctx.retval = mips32_pracc_queue_exec(ejtag_info, &ctx, NULL);
693 if (ctx.retval != ERROR_OK)
694 goto exit;
695
696 ctx.code_count = 0;
697 count = 0;
698 }
699 }
700 pracc_add(&ctx, 0, MIPS32_SYNC);
701 pracc_add(&ctx, 0, MIPS32_B(NEG16(ctx.code_count + 1))); /* jump to start */
702 pracc_add(&ctx, 0, MIPS32_MFC0(15, 31, 0)); /* restore $15 from DeSave*/
703
704 ctx.retval = mips32_pracc_queue_exec(ejtag_info, &ctx, NULL);
705 exit:
706 pracc_queue_free(&ctx);
707 return ctx.retval;
708 }
709
710 static int mips32_pracc_write_mem_generic(struct mips_ejtag *ejtag_info,
711 uint32_t addr, int size, int count, const void *buf)
712 {
713 struct pracc_queue_info ctx;
714 pracc_queue_init(&ctx);
715
716 const uint32_t *buf32 = buf;
717 const uint16_t *buf16 = buf;
718 const uint8_t *buf8 = buf;
719
720 while (count) {
721 ctx.code_count = 0;
722 ctx.store_count = 0;
723 int this_round_count = (count > 128) ? 128 : count;
724 uint32_t last_upper_base_addr = UPPER16((addr + 0x8000));
725
726 pracc_add(&ctx, 0, MIPS32_LUI(15, last_upper_base_addr)); /* load $15 with memory base address */
727
728 for (int i = 0; i != this_round_count; i++) {
729 uint32_t upper_base_addr = UPPER16((addr + 0x8000));
730 if (last_upper_base_addr != upper_base_addr) {
731 pracc_add(&ctx, 0, MIPS32_LUI(15, upper_base_addr)); /* if needed, change upper address in $15*/
732 last_upper_base_addr = upper_base_addr;
733 }
734
735 if (size == 4) {
736 pracc_add_li32(&ctx, 8, *buf32, 1); /* load with li32, optimize */
737 pracc_add(&ctx, 0, MIPS32_SW(8, LOWER16(addr), 15)); /* store word to memory */
738 buf32++;
739
740 } else if (size == 2) {
741 pracc_add(&ctx, 0, MIPS32_ORI(8, 0, *buf16)); /* load lower value */
742 pracc_add(&ctx, 0, MIPS32_SH(8, LOWER16(addr), 15)); /* store half word to memory */
743 buf16++;
744
745 } else {
746 pracc_add(&ctx, 0, MIPS32_ORI(8, 0, *buf8)); /* load lower value */
747 pracc_add(&ctx, 0, MIPS32_SB(8, LOWER16(addr), 15)); /* store byte to memory */
748 buf8++;
749 }
750 addr += size;
751 }
752
753 pracc_add_li32(&ctx, 8, ejtag_info->reg8, 0); /* restore $8 */
754
755 pracc_add(&ctx, 0, MIPS32_B(NEG16(ctx.code_count + 1))); /* jump to start */
756 pracc_add(&ctx, 0, MIPS32_MFC0(15, 31, 0)); /* restore $15 from DeSave */
757
758 ctx.retval = mips32_pracc_queue_exec(ejtag_info, &ctx, NULL);
759 if (ctx.retval != ERROR_OK)
760 goto exit;
761 count -= this_round_count;
762 }
763 exit:
764 pracc_queue_free(&ctx);
765 return ctx.retval;
766 }
767
768 int mips32_pracc_write_mem(struct mips_ejtag *ejtag_info, uint32_t addr, int size, int count, const void *buf)
769 {
770 int retval = mips32_pracc_write_mem_generic(ejtag_info, addr, size, count, buf);
771 if (retval != ERROR_OK)
772 return retval;
773
774 /**
775 * If we are in the cacheable region and cache is activated,
776 * we must clean D$ (if Cache Coherency Attribute is set to 3) + invalidate I$ after we did the write,
777 * so that changes do not continue to live only in D$ (if CCA = 3), but to be
778 * replicated in I$ also (maybe we wrote the istructions)
779 */
780 uint32_t conf = 0;
781 int cached = 0;
782
783 if ((KSEGX(addr) == KSEG1) || ((addr >= 0xff200000) && (addr <= 0xff3fffff)))
784 return retval; /*Nothing to do*/
785
786 mips32_cp0_read(ejtag_info, &conf, 16, 0);
787
788 switch (KSEGX(addr)) {
789 case KUSEG:
790 cached = (conf & MIPS32_CONFIG0_KU_MASK) >> MIPS32_CONFIG0_KU_SHIFT;
791 break;
792 case KSEG0:
793 cached = (conf & MIPS32_CONFIG0_K0_MASK) >> MIPS32_CONFIG0_K0_SHIFT;
794 break;
795 case KSEG2:
796 case KSEG3:
797 cached = (conf & MIPS32_CONFIG0_K23_MASK) >> MIPS32_CONFIG0_K23_SHIFT;
798 break;
799 default:
800 /* what ? */
801 break;
802 }
803
804 /**
805 * Check cachablitiy bits coherency algorithm
806 * is the region cacheable or uncached.
807 * If cacheable we have to synchronize the cache
808 */
809 if (cached == 3 || cached == 0) { /* Write back cache or write through cache */
810 uint32_t start_addr = addr;
811 uint32_t end_addr = addr + count * size;
812 uint32_t rel = (conf & MIPS32_CONFIG0_AR_MASK) >> MIPS32_CONFIG0_AR_SHIFT;
813 if (rel > 1) {
814 LOG_DEBUG("Unknown release in cache code");
815 return ERROR_FAIL;
816 }
817 retval = mips32_pracc_synchronize_cache(ejtag_info, start_addr, end_addr, cached, rel);
818 }
819
820 return retval;
821 }
822
823 int mips32_pracc_write_regs(struct mips_ejtag *ejtag_info, uint32_t *regs)
824 {
825 static const uint32_t cp0_write_code[] = {
826 MIPS32_MTC0(1, 12, 0), /* move $1 to status */
827 MIPS32_MTLO(1), /* move $1 to lo */
828 MIPS32_MTHI(1), /* move $1 to hi */
829 MIPS32_MTC0(1, 8, 0), /* move $1 to badvaddr */
830 MIPS32_MTC0(1, 13, 0), /* move $1 to cause*/
831 MIPS32_MTC0(1, 24, 0), /* move $1 to depc (pc) */
832 };
833
834 struct pracc_queue_info ctx;
835 pracc_queue_init(&ctx);
836
837 /* load registers 2 to 31 with li32, optimize */
838 for (int i = 2; i < 32; i++)
839 pracc_add_li32(&ctx, i, regs[i], 1);
840
841 for (int i = 0; i != 6; i++) {
842 pracc_add_li32(&ctx, 1, regs[i + 32], 0); /* load CPO value in $1 */
843 pracc_add(&ctx, 0, cp0_write_code[i]); /* write value from $1 to CPO register */
844 }
845 pracc_add(&ctx, 0, MIPS32_MTC0(15, 31, 0)); /* load $15 in DeSave */
846 pracc_add(&ctx, 0, MIPS32_LUI(1, UPPER16((regs[1])))); /* load upper half word in $1 */
847 pracc_add(&ctx, 0, MIPS32_B(NEG16(ctx.code_count + 1))); /* jump to start */
848 pracc_add(&ctx, 0, MIPS32_ORI(1, 1, LOWER16((regs[1])))); /* load lower half word in $1 */
849
850 ctx.retval = mips32_pracc_queue_exec(ejtag_info, &ctx, NULL);
851
852 ejtag_info->reg8 = regs[8];
853 ejtag_info->reg9 = regs[9];
854 pracc_queue_free(&ctx);
855 return ctx.retval;
856 }
857
858 int mips32_pracc_read_regs(struct mips_ejtag *ejtag_info, uint32_t *regs)
859 {
860 static int cp0_read_code[] = {
861 MIPS32_MFC0(8, 12, 0), /* move status to $8 */
862 MIPS32_MFLO(8), /* move lo to $8 */
863 MIPS32_MFHI(8), /* move hi to $8 */
864 MIPS32_MFC0(8, 8, 0), /* move badvaddr to $8 */
865 MIPS32_MFC0(8, 13, 0), /* move cause to $8 */
866 MIPS32_MFC0(8, 24, 0), /* move depc (pc) to $8 */
867 };
868
869 struct pracc_queue_info ctx;
870 pracc_queue_init(&ctx);
871
872 pracc_add(&ctx, 0, MIPS32_MTC0(1, 31, 0)); /* move $1 to COP0 DeSave */
873 pracc_add(&ctx, 0, MIPS32_LUI(1, PRACC_UPPER_BASE_ADDR)); /* $1 = MIP32_PRACC_BASE_ADDR */
874
875 for (int i = 2; i != 32; i++) /* store GPR's 2 to 31 */
876 pracc_add(&ctx, MIPS32_PRACC_PARAM_OUT + (i * 4),
877 MIPS32_SW(i, PRACC_OUT_OFFSET + (i * 4), 1));
878
879 for (int i = 0; i != 6; i++) {
880 pracc_add(&ctx, 0, cp0_read_code[i]); /* load COP0 needed registers to $8 */
881 pracc_add(&ctx, MIPS32_PRACC_PARAM_OUT + (i + 32) * 4, /* store $8 at PARAM OUT */
882 MIPS32_SW(8, PRACC_OUT_OFFSET + (i + 32) * 4, 1));
883 }
884 pracc_add(&ctx, 0, MIPS32_MFC0(8, 31, 0)); /* move DeSave to $8, reg1 value */
885 pracc_add(&ctx, MIPS32_PRACC_PARAM_OUT + 4, /* store reg1 value from $8 to param out */
886 MIPS32_SW(8, PRACC_OUT_OFFSET + 4, 1));
887
888 pracc_add(&ctx, 0, MIPS32_MFC0(1, 31, 0)); /* move COP0 DeSave to $1, restore reg1 */
889 pracc_add(&ctx, 0, MIPS32_B(NEG16(ctx.code_count + 1))); /* jump to start */
890 pracc_add(&ctx, 0, MIPS32_MTC0(15, 31, 0)); /* load $15 in DeSave */
891
892 ctx.retval = mips32_pracc_queue_exec(ejtag_info, &ctx, regs);
893
894 ejtag_info->reg8 = regs[8]; /* reg8 is saved but not restored, next called function should restore it */
895 ejtag_info->reg9 = regs[9];
896 pracc_queue_free(&ctx);
897 return ctx.retval;
898 }
899
900 /* fastdata upload/download requires an initialized working area
901 * to load the download code; it should not be called otherwise
902 * fetch order from the fastdata area
903 * 1. start addr
904 * 2. end addr
905 * 3. data ...
906 */
907 int mips32_pracc_fastdata_xfer(struct mips_ejtag *ejtag_info, struct working_area *source,
908 int write_t, uint32_t addr, int count, uint32_t *buf)
909 {
910 uint32_t handler_code[] = {
911 /* r15 points to the start of this code */
912 MIPS32_SW(8, MIPS32_FASTDATA_HANDLER_SIZE - 4, 15),
913 MIPS32_SW(9, MIPS32_FASTDATA_HANDLER_SIZE - 8, 15),
914 MIPS32_SW(10, MIPS32_FASTDATA_HANDLER_SIZE - 12, 15),
915 MIPS32_SW(11, MIPS32_FASTDATA_HANDLER_SIZE - 16, 15),
916 /* start of fastdata area in t0 */
917 MIPS32_LUI(8, UPPER16(MIPS32_PRACC_FASTDATA_AREA)),
918 MIPS32_ORI(8, 8, LOWER16(MIPS32_PRACC_FASTDATA_AREA)),
919 MIPS32_LW(9, 0, 8), /* start addr in t1 */
920 MIPS32_LW(10, 0, 8), /* end addr to t2 */
921 /* loop: */
922 write_t ? MIPS32_LW(11, 0, 8) : MIPS32_LW(11, 0, 9), /* from xfer area : from memory */
923 write_t ? MIPS32_SW(11, 0, 9) : MIPS32_SW(11, 0, 8), /* to memory : to xfer area */
924
925 MIPS32_BNE(10, 9, NEG16(3)), /* bne $t2,t1,loop */
926 MIPS32_ADDI(9, 9, 4), /* addi t1,t1,4 */
927
928 MIPS32_LW(8, MIPS32_FASTDATA_HANDLER_SIZE - 4, 15),
929 MIPS32_LW(9, MIPS32_FASTDATA_HANDLER_SIZE - 8, 15),
930 MIPS32_LW(10, MIPS32_FASTDATA_HANDLER_SIZE - 12, 15),
931 MIPS32_LW(11, MIPS32_FASTDATA_HANDLER_SIZE - 16, 15),
932
933 MIPS32_LUI(15, UPPER16(MIPS32_PRACC_TEXT)),
934 MIPS32_ORI(15, 15, LOWER16(MIPS32_PRACC_TEXT)),
935 MIPS32_JR(15), /* jr start */
936 MIPS32_MFC0(15, 31, 0), /* move COP0 DeSave to $15 */
937 };
938
939 if (source->size < MIPS32_FASTDATA_HANDLER_SIZE)
940 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
941
942 /* write program into RAM */
943 if (write_t != ejtag_info->fast_access_save) {
944 mips32_pracc_write_mem(ejtag_info, source->address, 4, ARRAY_SIZE(handler_code), handler_code);
945 /* save previous operation to speed to any consecutive read/writes */
946 ejtag_info->fast_access_save = write_t;
947 }
948
949 LOG_DEBUG("%s using 0x%.8" TARGET_PRIxADDR " for write handler", __func__, source->address);
950
951 uint32_t jmp_code[] = {
952 MIPS32_LUI(15, UPPER16(source->address)), /* load addr of jump in $15 */
953 MIPS32_ORI(15, 15, LOWER16(source->address)),
954 MIPS32_JR(15), /* jump to ram program */
955 MIPS32_NOP,
956 };
957
958 /* execute jump code, with no address check */
959 for (unsigned i = 0; i < ARRAY_SIZE(jmp_code); i++) {
960 int retval = wait_for_pracc_rw(ejtag_info);
961 if (retval != ERROR_OK)
962 return retval;
963
964 mips_ejtag_set_instr(ejtag_info, EJTAG_INST_DATA);
965 mips_ejtag_drscan_32_out(ejtag_info, jmp_code[i]);
966
967 /* Clear the access pending bit (let the processor eat!) */
968 mips32_pracc_finish(ejtag_info);
969 }
970
971 /* wait PrAcc pending bit for FASTDATA write, read address */
972 int retval = mips32_pracc_read_ctrl_addr(ejtag_info);
973 if (retval != ERROR_OK)
974 return retval;
975
976 /* next fetch to dmseg should be in FASTDATA_AREA, check */
977 if (ejtag_info->pa_addr != MIPS32_PRACC_FASTDATA_AREA)
978 return ERROR_FAIL;
979
980 /* Send the load start address */
981 uint32_t val = addr;
982 mips_ejtag_set_instr(ejtag_info, EJTAG_INST_FASTDATA);
983 mips_ejtag_fastdata_scan(ejtag_info, 1, &val);
984
985 retval = wait_for_pracc_rw(ejtag_info);
986 if (retval != ERROR_OK)
987 return retval;
988
989 /* Send the load end address */
990 val = addr + (count - 1) * 4;
991 mips_ejtag_set_instr(ejtag_info, EJTAG_INST_FASTDATA);
992 mips_ejtag_fastdata_scan(ejtag_info, 1, &val);
993
994 unsigned num_clocks = 0; /* like in legacy code */
995 if (ejtag_info->mode != 0)
996 num_clocks = ((uint64_t)(ejtag_info->scan_delay) * jtag_get_speed_khz() + 500000) / 1000000;
997
998 for (int i = 0; i < count; i++) {
999 jtag_add_clocks(num_clocks);
1000 mips_ejtag_fastdata_scan(ejtag_info, write_t, buf++);
1001 }
1002
1003 retval = jtag_execute_queue();
1004 if (retval != ERROR_OK) {
1005 LOG_ERROR("fastdata load failed");
1006 return retval;
1007 }
1008
1009 retval = mips32_pracc_read_ctrl_addr(ejtag_info);
1010 if (retval != ERROR_OK)
1011 return retval;
1012
1013 if (ejtag_info->pa_addr != MIPS32_PRACC_TEXT)
1014 LOG_ERROR("mini program did not return to start");
1015
1016 return retval;
1017 }

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)