1 #include <u.h>
2 #include <libc.h>
3 #include <bio.h>
4 #include "chain.h"
5 #include "debug.h"
6 #include "tap.h"
7 #include "lebo.h"
8 #include "bebo.h"
9 #include "jtag.h"
10 #include "icert.h"
11 #include "mpsse.h"
12 #include "/sys/src/9/kw/arm.h"
13 #include "mmu.h"
14
15 /*
16 * Read, paying special atention to anything called
17 * embedded-ice/debug of the arm core, normally
18 * there is a chapter called Debug or Debugging and some
19 * details sprinkled around.
20 * - ARM9E-S "Technical Reference Manual"
21 * - ARM7TDMI-S "Core Technical Reference Manual"
22 * - Open On-Chip Debugger thesis
23 * "Design and Implementation of an On-Chip Debug for Embedded
24 * Target Systems"
25 * - Application note 205 "Writing JTAG Sequences for Arm 9 Processors"
26 * The bit ordering on the last one is confusing/wrong, but the
27 * procedures for doing things clarify a lot.
28 */
29
30
31 /*
32 * BUG: print pack and unpack could be generated automatically
33 * except for the wild endianness of the instr. Minilanguage?
34 */
35
36 static char *
printech1(EiceChain1 * ec1,char * s,int ssz)37 printech1(EiceChain1 *ec1, char *s, int ssz)
38 {
39 char *e, *te;
40
41 te = s + ssz -1;
42
43 e = seprint(s, te, "rwdata: %#8.8ux\n", ec1->rwdata);
44 e = seprint(e, te, "wptandbkpt: %1.1d\n", ec1->wptandbkpt);
45 e = seprint(e, te, "sysspeed: %1.1d\n", ec1->sysspeed);
46 e = seprint(e, te, "instr: %#8.8ux\n", ec1->instr);
47 return e;
48 }
49
50 static int
packech1(Chain * ch,EiceChain1 * ec1)51 packech1(Chain *ch, EiceChain1 *ec1)
52 {
53 EiceChain1 lec;
54 uchar unused;
55
56 unused = 0;
57
58 lec.instr = hmsbputl(&ec1->instr);
59 hbeputl(&lec.rwdata, ec1->rwdata);
60
61 putbits(ch, &lec.rwdata, RWDataSz);
62 putbits(ch, &unused, 1);
63 putbits(ch, &lec.wptandbkpt, WpTanDBKptSz);
64
65 putbits(ch, &ec1->sysspeed, SysSpeedSz);
66 putbits(ch, &lec.instr, InstrSz);
67
68 return 0;
69 }
70
71 static int
unpackech1(EiceChain1 * ec1,Chain * ch)72 unpackech1(EiceChain1 *ec1, Chain *ch)
73 {
74 uchar unused;
75
76 unused = 0;
77
78
79 getbits(&ec1->rwdata, ch, RWDataSz);
80 getbits(&unused, ch, 1);
81 getbits(&ec1->wptandbkpt, ch, WpTanDBKptSz);
82 getbits(&ec1->sysspeed, ch, SysSpeedSz);
83 getbits(&ec1->instr, ch, InstrSz);
84
85 ec1->instr = msbhgetl(&ec1->instr);
86 ec1->rwdata = lehgetl(&ec1->rwdata);
87
88 return 0;
89 }
90
91
92 static char *
printech2(EiceChain2 * ec2,char * s,int ssz)93 printech2(EiceChain2 *ec2, char *s, int ssz)
94 {
95 char *e, *te;
96
97 te = s + ssz -1;
98
99 e = seprint(s, te, "data: %#8.8ux\n", ec2->data);
100 e = seprint(e, te, "addr: %#2.2ux\n", ec2->addr);
101 e = seprint(e, te, "rw: %1.1d\n", ec2->rw);
102 return e;
103 }
104
105 static int
valregaddr(uchar addr)106 valregaddr(uchar addr)
107 {
108 if(addr <= CtlMskReg)
109 return 1;
110 if( (addr&Wp0) <= CtlMskReg || (addr&Wp1) <= CtlMskReg)
111 return 1;
112 return 0;
113 }
114
115 static int
packech2(Chain * ch,EiceChain2 * ec2)116 packech2(Chain *ch, EiceChain2 *ec2)
117 {
118 EiceChain2 lec;
119
120 if(!valregaddr(ec2->addr))
121 return -1;
122
123 hleputl(&lec.data, ec2->data);
124
125 putbits(ch, &lec.data, DataSz);
126 putbits(ch, &ec2->addr, AddrSz);
127 putbits(ch, &ec2->rw, RWSz);
128 return 0;
129 }
130
131 static int
unpackech2(EiceChain2 * ec2,Chain * ch)132 unpackech2(EiceChain2 *ec2, Chain *ch)
133 {
134
135 getbits(&ec2->data, ch, DataSz);
136 getbits(&ec2->addr, ch, AddrSz);
137 getbits(&ec2->rw, ch, RWSz);
138
139 if(!valregaddr(ec2->addr))
140 return -1;
141
142 ec2->data = lehgetl(&ec2->data);
143
144 return 0;
145 }
146
147
148 static char *
printwp(EiceWp * wp,char * s,int ssz)149 printwp(EiceWp *wp, char *s, int ssz)
150 {
151 char *e, *te;
152
153 te = s + ssz -1;
154
155 e = seprint(s, te, "addrval: %#8.8ux\n", wp->addrval);
156 e = seprint(e, te, "addmsk: %#8.8ux\n", wp->addrmsk);
157 e = seprint(e, te, "dataval: %#8.8ux\n", wp->dataval);
158 e = seprint(e, te, "datamsk: %#8.8ux\n", wp->datamsk);
159
160 e = seprint(e, te, "ctlval: %#4.4ux\n", wp->ctlval);
161 e = seprint(e, te, "ctlmsk: %#2.2ux\n", wp->ctlmsk);
162 return e;
163 }
164
165 static char *
printregs(EiceRegs * regs,char * s,int ssz)166 printregs(EiceRegs *regs, char *s, int ssz)
167 {
168 char *e, *te, i;
169
170 te = s + ssz -1;
171
172 e = seprint(s, te, "debug: %#2.2ux\n", regs->debug);
173 e = seprint(e, te, "debsts: %#2.2ux\n", regs->debsts);
174 e = seprint(e, te, "veccat: %#2.2ux\n", regs->veccat);
175 e = seprint(e, te, "debcomctl: %#2.2ux\n", regs->debcomctl);
176 e = seprint(e, te, "debcomdata: %#8.8ux\n", regs->debcomdata);
177
178 for(i = 0; i<nelem(regs->wp); i++)
179 e = printwp(regs->wp + i, e, ssz+(s-e));
180 return e;
181 }
182
183 static u32int
unpackcpuid(uchar * v)184 unpackcpuid(uchar *v)
185 {
186 u32int id;
187
188 id = lehgetl(v);
189 return id;
190 }
191
192 static void
prcpuid(u32int id)193 prcpuid(u32int id)
194 {
195
196 fprint(2, "ID: %#8.8ux\n", id);
197 fprint(2, "Must be 1: %d\n", id&1);
198 fprint(2, "Manufacturer id: %#lux\n", MANID(id));
199 fprint(2, "Part no: %#lux\n", PARTNO(id));
200 fprint(2, "Version: %#lux\n", VERS(id));
201 return;
202 }
203
204
205
206 int
setinst(JMedium * jmed,uchar inst,int nocommit)207 setinst(JMedium *jmed, uchar inst, int nocommit)
208 {
209 int res, com;
210 ShiftTDesc req;
211 uchar buf[1+ShiftMarg];
212
213 memset(buf, 0, 5);
214 buf[0] = inst;
215 com = 0;
216
217 dprint(Djtag, "Setting jtag instr: %#2.2ux, commit: %d\n",
218 inst, !nocommit);
219 if(nocommit)
220 com = ShiftNoCommit;
221 req.reg = TapIR;
222 req.buf = buf;
223 req.nbits = InLen;
224 req.op = ShiftOut|com;
225
226 res = tapshift(jmed, &req, nil, jmed->tapcpu);
227 if(res < 0){
228 werrstr("setinst: shifting instruction %#2.2ux for jtag", inst);
229 return -1;
230 }
231 return res;
232 }
233
234 int
icesetreg(JMedium * jmed,int regaddr,u32int val)235 icesetreg(JMedium *jmed, int regaddr, u32int val)
236 {
237 Chain ch;
238 ShiftTDesc req;
239 EiceChain2 ec2;
240 char debugstr[128];
241 int res;
242
243 dprint(Dice, "Set eice 2 reg[%#2.2ux] to %#8.8ux\n", regaddr, val);
244 ec2.data = val;
245 ec2.addr = regaddr;
246 ec2.rw = 1;
247 memset(&ch, 0, sizeof ch);
248
249
250 res = packech2(&ch, &ec2);
251 if(res < 0)
252 return -1;
253 if(debug[Dchain] || debug[DAll]){
254 printech2(&ec2, debugstr, sizeof debugstr);
255 fprint(2, "%s", debugstr);
256 printchain(&ch);
257 }
258 req.reg = TapDR;
259 req.buf = ch.buf;
260 req.nbits = EiceCh2Len;
261 req.op = ShiftOut;
262 res = tapshift(jmed, &req, nil, jmed->tapcpu);
263 if(res < 0)
264 return -1;
265
266 return 0;
267 }
268
269
270 u32int
icegetreg(JMedium * jmed,int regaddr)271 icegetreg(JMedium *jmed, int regaddr)
272 {
273 Chain ch;
274 ShiftTDesc req;
275 int res;
276 EiceChain2 ec2;
277 char debugstr[128];
278
279 ec2.data = 0;
280 ec2.addr = regaddr;
281 ec2.rw = 0;
282 memset(&ch, 0, sizeof ch);
283
284 res = packech2(&ch, &ec2);
285 if(res < 0)
286 return -1;
287 if(debug[Dchain] || debug[DAll]){
288 printech2(&ec2, debugstr, sizeof debugstr);
289 fprint(2, "%s", debugstr);
290 printchain(&ch);
291 }
292 req.reg = TapDR;
293 req.buf = ch.buf;
294 req.nbits = EiceCh2Len;
295 req.op = ShiftOut;
296 res = tapshift(jmed, &req, nil, jmed->tapcpu);
297 if(res < 0)
298 return -1;
299 req.reg = TapDR;
300 req.buf = ch.buf;
301 req.nbits = EiceCh2Len;
302 req.op = ShiftOut|ShiftIn;
303 res = tapshift(jmed, &req, nil, jmed->tapcpu);
304 if(res < 0)
305 return -1;
306 ch.b = 0;
307 ch.e = EiceCh2Len;
308 res = unpackech2(&ec2, &ch);
309 if(res < 0)
310 return -1;
311 if(debug[Dice] || debug[DAll]){
312 printchain(&ch);
313 printech2(&ec2, debugstr, sizeof debugstr);
314 fprint(2, "Get eice 2 reg[%#2.2ux] to %#8.8ux\n", regaddr, ec2.data);
315 }
316 return ec2.data;
317 }
318
319 int
setchain(JMedium * jmed,int commit,uchar chain)320 setchain(JMedium *jmed, int commit, uchar chain)
321 {
322 ShiftTDesc req;
323 uchar data[1+ShiftMarg];
324 int res, com;
325
326 dprint(Dice, "Set chain %d, chain before %d\n", chain, jmed->currentch);
327 if(jmed->currentch == chain)
328 return 0;
329 res = setinst(jmed, InScanN, 1);
330 if(res < 0)
331 return -1;
332 data[0] = chain;
333 com = 0;
334 if(!commit)
335 com = ShiftNoCommit;
336 req.reg = TapDR;
337 req.buf = data;
338 req.nbits = 5;
339 req.op = ShiftPauseIn|ShiftOut|com;
340 res = tapshift(jmed, &req, nil, jmed->tapcpu);
341 if(res < 0)
342 return -1;
343 res = setinst(jmed, InTest, 1);
344 if(res < 0)
345 return -1;
346 jmed->currentch = chain;
347 return 0;
348 }
349
350
351 int
armgofetch(JMedium * jmed,u32int instr,int sysspeed)352 armgofetch(JMedium *jmed, u32int instr, int sysspeed)
353 {
354 char debugstr[128];
355 ShiftTDesc req;
356 EiceChain1 ec1;
357 Chain ch;
358 int res;
359
360 ec1.instr = instr;
361 ec1.sysspeed = sysspeed;
362 ec1.wptandbkpt = 0;
363 ec1.rwdata = 0;
364 memset(&ch, 0, sizeof (Chain));
365 res = packech1(&ch, &ec1);
366 if(res < 0)
367 return -1;
368 if(debug[Dchain] || debug[DAll]){
369 printech1(&ec1, debugstr, sizeof debugstr);
370 fprint(2, "%s", debugstr);
371 printchain(&ch);
372 }
373 req.reg = TapDR;
374 req.buf = ch.buf;
375 req.nbits = ch.e-ch.b;
376 req.op = ShiftOut|ShiftPauseOut|ShiftPauseIn;
377 res = tapshift(jmed, &req, nil, jmed->tapcpu);
378 if(res < 0)
379 return -1;
380 return 0;
381
382 }
383
384 int
armgetexec(JMedium * jmed,int nregs,u32int * regs,u32int inst)385 armgetexec(JMedium *jmed, int nregs, u32int *regs, u32int inst)
386 {
387 ShiftTDesc req;
388 int i, res, flags;
389 uchar *buf;
390 ShiftRDesc *replies;
391
392 dprint(Darm, "Exec: %#8.8ux\n", inst);
393 replies = mallocz(nregs*sizeof(ShiftRDesc), 1);
394 if(replies == nil)
395 sysfatal("read, no mem %r");
396 buf = mallocz(EiceCh1Len+ShiftMarg, 1);
397 if(buf == nil)
398 sysfatal("read, no mem %r");
399 armgofetch(jmed, inst, 0);
400 /* INST in decode stage */
401 armgofetch(jmed, ARMNOP, 0);
402 /* INST in execute stage */
403 armgofetch(jmed, ARMNOP, 0);
404 /* INST in access stage */
405 flags = ShiftAsync|ShiftIn|ShiftPauseIn|ShiftPauseOut;
406 for(i = 0; i < nregs; i++){
407 req.reg = TapDR;
408 req.buf = buf;
409 req.nbits = EiceCh1Len;
410 req.op = flags;
411 res = tapshift(jmed, &req, &replies[i], jmed->tapcpu);
412 if(res < 0)
413 return -1;
414 }
415 for(i = 0; i < nregs; i++){
416 res = jmed->rdshiftrep(jmed, buf, &replies[i]);
417 if(res < 0)
418 return -1;
419 regs[i] = *(u32int *)buf;
420 dprint(Darm, "Read [%d]: %#8.8ux\n", i, regs[i]);
421 }
422 armgofetch(jmed, ARMNOP, 0);
423 /* INST in writeback stage */
424 armgofetch(jmed, ARMNOP, 0);
425 /* INST end, pipeline full of NOPs */
426
427 free(buf);
428 free(replies);
429 return 0;
430 }
431
432 int
armsetexec(JMedium * jmed,int nregs,u32int * regs,u32int inst)433 armsetexec(JMedium *jmed, int nregs, u32int *regs, u32int inst)
434 {
435 ShiftTDesc req;
436 int i, res, flags;
437 uchar *buf;
438
439 ShiftRDesc *replies;
440
441 dprint(Darm, "Exec: %#8.8ux\n", inst);
442 replies = mallocz(nregs*sizeof(ShiftRDesc), 1);
443 if(replies == nil)
444 sysfatal("read, no mem %r");
445 buf = mallocz(EiceCh1Len+ShiftMarg, 1);
446 if(buf == nil)
447 sysfatal("readregs, no mem %r");
448 armgofetch(jmed, inst, 0);
449 /* STMIA in decode stage */
450 armgofetch(jmed, ARMNOP, 0);
451 /* STMIA in execute stage */
452 armgofetch(jmed, ARMNOP, 0);
453 /* STMIA in memory acess stage */
454 flags = ShiftOut|ShiftPauseIn|ShiftPauseOut;
455 for(i = 0; i < nregs; i++){
456 *(u32int *)buf = regs[i];
457 dprint(Darm, "Set [%d]: %#8.8ux\n", i, regs[i]);
458 req.reg = TapDR;
459 req.buf = buf;
460 req.nbits = EiceCh1Len;
461 req.op = flags;
462 res = tapshift(jmed, &req, nil, jmed->tapcpu);
463 if(res < 0)
464 return -1;
465 }
466 armgofetch(jmed, ARMNOP, 0);
467 /* STMIA in writeback stage */
468 armgofetch(jmed, ARMNOP, 0);
469 /* STMIA end, pipeline full of NOPs */
470
471 free(buf);
472 free(replies);
473 return 0;
474 }
475
476 /* reads r0-r15 to regs if bits of mask are 1 */
477 static int
armgetregs(JMedium * jmed,u32int mask,u32int * regs)478 armgetregs(JMedium *jmed, u32int mask, u32int *regs)
479 {
480 int ireps, nregs, r, i;
481 u32int *regrd;
482
483 nregs = 0;
484 ireps = 0;
485 for(i = 0; i < 16; i++){
486 if( (1 << i) & mask)
487 nregs++;
488 }
489 regrd = mallocz(nregs*sizeof(u32int), 1);
490 if(regrd == nil)
491 sysfatal("read, no mem %r");
492
493 r = armgetexec(jmed, nregs, regrd, ARMSTMIA|mask);
494 if(r < 0)
495 return -1;
496
497 for(i = 0; i < 16; i++){
498 if( (1 << i) & mask){
499 regs[i] = regrd[ireps++];
500 dprint(Darm, "rd register r%d: %#8.8ux\n", i, regs[i]);
501 }
502 }
503 free(regrd);
504 return 0;
505 }
506 /* sets r0-r15 to regs if bits of mask are 1 */
507 int
armsetregs(JMedium * jmed,int mask,u32int * regs)508 armsetregs(JMedium *jmed, int mask, u32int *regs)
509 {
510 int ireps, nregs, r, i;
511 u32int *regrw;
512
513 nregs = 0;
514 ireps = 0;
515 for(i = 0; i < 16; i++){
516 if( (1 << i) & mask)
517 nregs++;
518 }
519 regrw = mallocz(nregs*sizeof(u32int), 1);
520 if(regrw == nil)
521 sysfatal("read, no mem %r");
522 for(i = 0; i < 16; i++){
523 if( (1 << i) & mask){
524 regrw[ireps++] = regs[i];
525 dprint(Darm, "wr register r%d: %#8.8ux\n", i, regs[i]);
526 }
527 }
528 r = armsetexec(jmed, nregs, regrw, ARMLDMIA|mask);
529 if(r < 0)
530 return -1;
531
532 free(regrw);
533 return 0;
534 }
535
536 static void
armprctxt(ArmCtxt * ctxt)537 armprctxt(ArmCtxt *ctxt)
538 {
539 int i;
540
541 fprint(2, "Arm is in debug: %d\nregs\n", ctxt->debug);
542 for(i = 0; i < 16; i++)
543 fprint(2, "r%d: %#8.8ux\n", i, ctxt->r[i]);
544 fprint(2, "cpsr: %#8.8ux\n", ctxt->cpsr);
545 fprint(2, "spsr: %#8.8ux\n", ctxt->spsr);
546 }
547
548 char *
armsprctxt(ArmCtxt * ctxt,char * s,int ssz)549 armsprctxt(ArmCtxt *ctxt, char *s, int ssz)
550 {
551 char *e, *te;
552 int i;
553
554 te = s + ssz -1;
555
556 e = seprint(s, te, "Arm is in debug: %d\nregs\n", ctxt->debug);
557 for(i = 0; i < 16; i++)
558 e = seprint(e, te, "r%d: %#8.8ux\n", i, ctxt->r[i]);
559 e = seprint(e, te, "cpsr: %#8.8ux\n", ctxt->cpsr);
560 e = seprint(e, te, "spsr: %#8.8ux\n", ctxt->spsr);
561 return e;
562 }
563
564 static char dbgstr[4*1024];
565
566 int
armsavectxt(JMedium * jmed,ArmCtxt * ctxt)567 armsavectxt(JMedium *jmed, ArmCtxt *ctxt)
568 {
569 int res;
570
571 res = setchain(jmed, 0, 1);
572 if(res < 0)
573 goto Error;
574
575 res = armgetregs(jmed, 0xffff, ctxt->r);
576 if(res < 0)
577 goto Error;
578 res = armgofetch(jmed, ARMMRSr0CPSR, 0);
579 if(res < 0)
580 goto Error;
581 res = armgetexec(jmed, 1, &ctxt->cpsr, ARMSTMIA|0x0001);
582 if(res < 0)
583 goto Error;
584 res = armgofetch(jmed, ARMMRSr0SPSR, 0);
585 if(res < 0)
586 goto Error;
587 res = armgetexec(jmed, 1, &ctxt->spsr, ARMSTMIA|0x0001);
588 if(res < 0)
589 goto Error;
590 res = mmurdregs(jmed, ctxt);
591 if(res < 0){
592 werrstr("mmurdregs %r");
593 return -1;
594 }
595 if(debug[Dmmu] || debug[DAll]){
596 printmmuregs(ctxt, dbgstr, sizeof dbgstr);
597 dprint(Dfs, "MMU state:\n%s\n", dbgstr);
598 }
599 if(debug[Dctxt] || debug[DAll]){
600 fprint(2, "Arm save ctxt\n");
601 armprctxt(ctxt);
602 }
603 return 0;
604 Error:
605 return -1;
606 }
607
608 static int
armjmpctxt(JMedium * jmed,ArmCtxt * ctxt)609 armjmpctxt(JMedium *jmed, ArmCtxt *ctxt)
610 {
611 int res;
612
613 if(debug[Dctxt] || debug[DAll]){
614 fprint(2, "Arm jmp ctxt\n");
615 armprctxt(ctxt);
616 }
617 res = armsetexec(jmed, 1, &ctxt->cpsr, ARMLDMIA|0x0001);
618 if(res < 0)
619 return -1;
620 res = armgofetch(jmed, ARMMSRr0CPSR, 0);
621 if(res < 0)
622 return -1;
623 /* it is quite important this is the last instr for PC calculations */
624 ctxt->r[15] += ctxt->pcadjust;
625 res = armsetregs(jmed, 0xffff, ctxt->r);
626 if(res < 0)
627 return -1;
628
629 return 0;
630 }
631
632
633 int
armfastexec(JMedium * jmed,u32int inst)634 armfastexec(JMedium *jmed, u32int inst)
635 {
636 int res;
637
638 dprint(Darm, "Exec: %#8.8ux\n", inst);
639 res = armgofetch(jmed, ARMNOP, 0);
640 if(res < 0)
641 return -1;
642
643 res = armgofetch(jmed, ARMNOP, 0);
644 if(res < 0)
645 return -1;
646 res = armgofetch(jmed, ARMNOP, 0);
647 if(res < 0)
648 return -1;
649 res = armgofetch(jmed, inst, 0);
650 if(res < 0)
651 return -1;
652 res = armgofetch(jmed, ARMNOP, 1);
653 if(res < 0)
654 return -1;
655 return 0;
656 }
657
658 int
icedebugstate(JMedium * jmed)659 icedebugstate(JMedium *jmed)
660 {
661 int res;
662
663 res = setchain(jmed, ChCommit, 2);
664 if(res < 0)
665 return 0;
666 return icegetreg(jmed, DebStsReg) & DBGACK;
667 }
668
669 int
icewaitdebug(JMedium * jmed)670 icewaitdebug(JMedium *jmed)
671 {
672 int i, res;
673
674 res = setchain(jmed, ChCommit, 2);
675 if(res < 0)
676 return -1;
677
678 for(i = 0; i < 20; i ++){
679 if(icedebugstate(jmed))
680 break;
681 sleep(100);
682 }
683 if( i == 20)
684 return -1;
685
686 icesetreg(jmed, DebugCtlReg, INTDIS|DBGACK); /* clear RQ */
687 return 0;
688 }
689
690 int
armrdmemwd(JMedium * jmed,u32int addr,u32int * data,int sz)691 armrdmemwd(JMedium *jmed, u32int addr, u32int *data, int sz)
692 {
693 int res;
694 u32int d, byte;
695
696 res = setchain(jmed, ChCommit, 1);
697 if(res < 0)
698 sysfatal("setchain %r");
699 byte = 0;
700 if(sz == 1)
701 byte = BYTEWDTH;
702 /* load address in r0 */
703 res = armsetexec(jmed, 1, &addr, ARMLDMIA|0x0001);
704 if(res < 0)
705 return -1;
706
707 /* LDR r1, [r0] place data in r1 */
708 res = armfastexec(jmed, byte|ARMLDRindr1xr0);
709 if(res < 0)
710 return -1;
711
712 setinst(jmed, InRestart, 0);
713 res = icewaitdebug(jmed);
714 if(res < 0)
715 return -1;
716 res = setchain(jmed, ChCommit, 1);
717 if(res < 0)
718 sysfatal("setchain %r");
719 armgetexec(jmed, 1, &d, byte|ARMSTMIA|0x0002);
720
721 *data = d;
722 dprint(Dmem, "Read data %#8.8ux addr %#8.8ux \n",
723 d, addr);
724 return sz;
725 }
726
727 int
armwrmemwd(JMedium * jmed,u32int addr,u32int data,int sz)728 armwrmemwd(JMedium *jmed, u32int addr, u32int data, int sz)
729 {
730 int res;
731 u32int byte;
732
733 dprint(Dmem, "Write data %#8.8ux addr %#8.8ux \n",
734 data, addr);
735 res = setchain(jmed, ChCommit, 1);
736 if(res < 0)
737 sysfatal("setchain %r");
738 byte = 0;
739 if(sz == 1)
740 byte = BYTEWDTH;
741 /* load address in r0 */
742 res = armsetexec(jmed, 1, &addr, ARMLDMIA|0x0001);
743 if(res < 0)
744 return -1;
745 /* load data in r1 */
746 res = armsetexec(jmed, 1, &data, byte|ARMLDMIA|0x0002);
747 if(res < 0)
748 return -1;
749
750 /* STR [r0], r1 place data in [r0] */
751 res = armfastexec(jmed, ARMSTRindxr0r1);
752 if(res < 0)
753 return -1;
754
755 setinst(jmed, InRestart, 0);
756 res = icewaitdebug(jmed);
757 if(res < 0)
758 return -1;
759 return sz;
760 }
761
762
763 u32int
armidentify(JMedium * jmed)764 armidentify(JMedium *jmed)
765 {
766 uchar *buf;
767 ShiftTDesc req;
768 u32int cpuid;
769 int res, i;
770
771 //if(jmed->motherb == Sheeva)
772 // jmed->resets(jmed->mdata, 0, 1);
773 buf = malloc(sizeof(u32int)*0x100+ ShiftMarg);
774 if(buf == nil)
775 sysfatal("memory");
776
777 for(i = 0; i < sizeof(u32int)*0x100; i++)
778 buf[i] = i; /* just a pattern to see in debugging */
779
780 req.reg = TapDR;
781 req.buf = buf;
782 req.nbits = sizeof(u32int)*0x100; /* Bug by 8? */
783 req.op = ShiftOut|ShiftIn;
784 res = tapshift(jmed, &req, nil, jmed->tapcpu);
785 if(res < 0){
786 free(buf);
787 return ~0;
788 }
789 //if(jmed->motherb == Sheeva)
790 // jmed->resets(jmed->mdata, 0, 0);
791 cpuid = unpackcpuid(buf);
792 if(cpuid != jmed->taps[jmed->tapcpu].hwid){
793 fprint(2, "cpuid: %#8.8ux != %#8.8ux\n", cpuid, jmed->taps[jmed->tapcpu].hwid);
794 free(buf);
795 return ~0;
796 }
797 prcpuid(cpuid);
798 free(buf);
799 return cpuid;
800 }
801
802 /* see if the fixed bypass value is ok */
803 int
armbpasstest(JMedium * jmed)804 armbpasstest(JMedium *jmed)
805 {
806 ShiftTDesc req;
807 uchar buf[2+ShiftMarg];
808 int res;
809
810 memset(buf, 0xff, sizeof(buf));
811 req.reg = TapIR;
812 req.buf = buf;
813 req.nbits = 2+InLen;
814 req.op = ShiftOut|ShiftIn;
815 res = tapshift(jmed, &req, nil, jmed->tapcpu);
816 if(res < 0)
817 sysfatal("jmed->regshift %r");
818 if((buf[0] & 0xf) != 0x1){
819 fprint(2, "bad bypass: %#2.2ux\n", buf[0]);
820 return -1;
821 }
822
823 return 0;
824 }
825
826 /* BUG: werrstr in the inner functions to indicate error, warnings... */
827
828
829 int
icewaitentry(JMedium * jmed,ArmCtxt * ctxt)830 icewaitentry(JMedium *jmed, ArmCtxt *ctxt)
831 {
832 int res;
833
834 if(ctxt->debugreas == NoReas){
835 werrstr("No debug activated");
836 return -1;
837 }
838 res = setchain(jmed, ChCommit, 2);
839 if(res < 0)
840 return -1;
841 res = icewaitdebug(jmed);
842 if(res < 0)
843 return -1;
844
845 res = setchain(jmed, ChNoCommit, 1);
846 if(res < 0)
847 return -1;
848
849 /* BUG: should change to Arm from Thumb or Jazelle, adjust, keep PC.
850 * If I ever come down to doing this, Remember to repeat Thumb inst
851 * to be endian independant...
852 */
853 res = armsavectxt(jmed, ctxt);
854 if(res < 0)
855 return -1;
856 ctxt->debug = 1;
857
858 ctxt->pcadjust = 0; /* BUG: Thumb not impl */
859 ctxt->r[15] -= 6*ArmInstSz;
860 switch(ctxt->debugreas){
861 case BreakReas:
862 case VeccatReas:
863 ctxt->pcadjust = -2*ArmInstSz;
864 break;
865 case DebugReas:
866 break;
867 }
868 return 0;
869 }
870
871 int
iceenterdebug(JMedium * jmed,ArmCtxt * ctxt)872 iceenterdebug(JMedium *jmed, ArmCtxt *ctxt)
873 {
874 int res;
875
876 res = setchain(jmed, ChCommit, 2);
877 if(res < 0)
878 return -1;
879
880 //if(jmed->motherb == Sheeva)
881 // jmed->resets(jmed->mdata, 0, 1);
882 if(!(icegetreg(jmed, DebStsReg) & DBGACK)){
883 icesetreg(jmed, DebugCtlReg, DBGRQ); /* freeze */
884 }
885
886 //if(jmed->motherb == Sheeva)
887 // jmed->resets(jmed->mdata, 0, 0);
888 ctxt->debugreas = DebugReas;
889 res = icewaitentry(jmed, ctxt);
890 if(res < 0)
891 return -1;
892 ctxt->exitreas = NoReas;
893 return 0;
894 }
895
896
897 /*
898 * The branch is the way to exit debug permanently
899 * no branch and you fall back to debug
900 * The context needs to be restored (some register needs
901 * to be written), don't know why
902 * but you will fall back to debug if not, no matter what doc says.
903 * The bypass is not mentioned to be necessary anywhere, but
904 * the feroceon will not restart without it.
905 */
906
907 int
iceexitdebug(JMedium * jmed,ArmCtxt * ctxt)908 iceexitdebug(JMedium *jmed, ArmCtxt *ctxt)
909 {
910 int res, i;
911 uchar wctl;
912 u32int sts;
913
914 res = setchain(jmed, ChCommit, 1);
915 if(res < 0)
916 return -1;
917
918 res = armjmpctxt(jmed, ctxt);
919 if(res < 0)
920 return -1;
921
922 /* 4 entry to debug, Store(does not count) 3 NOPS, Branch = -8 */
923 res = armfastexec(jmed, ARMBRIMM|0xfffffb);
924 if(res < 0)
925 return -1;
926
927 res = setchain(jmed, ChCommit, 2);
928 if(res < 0)
929 return -1;
930
931 wctl = icegetreg(jmed, Wp0|CtlValReg);
932 if(ctxt->exitreas != BreakReqReas)
933 icesetreg(jmed, Wp0|CtlValReg, wctl&~EnableWPCtl);
934
935 if(ctxt->exitreas != VeccatReqReas)
936 icesetreg(jmed, VecCatReg, 0);
937 icesetreg(jmed, DebugCtlReg, 0); /* clear all,*/
938 setinst(jmed, InBypass, 0);
939 setinst(jmed, InRestart, 0);
940 sleep(100);
941 res = setchain(jmed, ChCommit, 2);
942 if(res < 0)
943 return -1;
944
945 for(i = 0; i < 10; i ++){
946 sts = icegetreg(jmed, DebStsReg);
947 if((sts&DBGACK) == 0)
948 break;
949 sleep(100);
950 }
951 if( i == 10)
952 return -1;
953
954 switch(ctxt->exitreas){
955 case NoReas:
956 ctxt->debugreas = NoReas;
957 break;
958 case VeccatReqReas:
959 ctxt->debugreas = VeccatReas;
960 break;
961 case BreakReqReas:
962 ctxt->debugreas = BreakReas;
963 break;
964 default:
965 ctxt->debugreas = NoReas;
966 break;
967 }
968 ctxt->debug = 0;
969 return 0;
970 }
971