1/* 2 * Copyright (C) 2004 Axis Communications AB 3 * 4 * Code for handling break 8, hardware breakpoint, single step, and serial 5 * port exceptions for kernel debugging purposes. 6 */ 7 8#include <hwregs/intr_vect.h> 9 10 ;; Exported functions. 11 .globl kgdb_handle_exception 12 13kgdb_handle_exception: 14 15;; Create a register image of the caller. 16;; 17;; First of all, save the ACR on the stack since we need it for address calculations. 18;; We put it into the register struct later. 19 20 subq 4, $sp 21 move.d $acr, [$sp] 22 23;; Now we are free to use ACR all we want. 24;; If we were running this handler with interrupts on, we would have to be careful 25;; to save and restore CCS manually, but since we aren't we treat it like every other 26;; register. 27 28 move.d reg, $acr 29 move.d $r0, [$acr] ; Save R0 (start of register struct) 30 addq 4, $acr 31 move.d $r1, [$acr] ; Save R1 32 addq 4, $acr 33 move.d $r2, [$acr] ; Save R2 34 addq 4, $acr 35 move.d $r3, [$acr] ; Save R3 36 addq 4, $acr 37 move.d $r4, [$acr] ; Save R4 38 addq 4, $acr 39 move.d $r5, [$acr] ; Save R5 40 addq 4, $acr 41 move.d $r6, [$acr] ; Save R6 42 addq 4, $acr 43 move.d $r7, [$acr] ; Save R7 44 addq 4, $acr 45 move.d $r8, [$acr] ; Save R8 46 addq 4, $acr 47 move.d $r9, [$acr] ; Save R9 48 addq 4, $acr 49 move.d $r10, [$acr] ; Save R10 50 addq 4, $acr 51 move.d $r11, [$acr] ; Save R11 52 addq 4, $acr 53 move.d $r12, [$acr] ; Save R12 54 addq 4, $acr 55 move.d $r13, [$acr] ; Save R13 56 addq 4, $acr 57 move.d $sp, [$acr] ; Save SP (R14) 58 addq 4, $acr 59 60 ;; The ACR register is already saved on the stack, so pop it from there. 61 move.d [$sp],$r0 62 move.d $r0, [$acr] 63 addq 4, $acr 64 65 move $bz, [$acr] 66 addq 1, $acr 67 move $vr, [$acr] 68 addq 1, $acr 69 move $pid, [$acr] 70 addq 4, $acr 71 move $srs, [$acr] 72 addq 1, $acr 73 move $wz, [$acr] 74 addq 2, $acr 75 move $exs, [$acr] 76 addq 4, $acr 77 move $eda, [$acr] 78 addq 4, $acr 79 move $mof, [$acr] 80 addq 4, $acr 81 move $dz, [$acr] 82 addq 4, $acr 83 move $ebp, [$acr] 84 addq 4, $acr 85 move $erp, [$acr] 86 addq 4, $acr 87 move $srp, [$acr] 88 addq 4, $acr 89 move $nrp, [$acr] 90 addq 4, $acr 91 move $ccs, [$acr] 92 addq 4, $acr 93 move $usp, [$acr] 94 addq 4, $acr 95 move $spc, [$acr] 96 addq 4, $acr 97 98;; Skip the pseudo-PC. 99 addq 4, $acr 100 101;; Save the support registers in bank 0 - 3. 102 clear.d $r1 ; Bank counter 103 move.d sreg, $acr 104 105;; Bank 0 106 move $r1, $srs 107 nop 108 nop 109 nop 110 move $s0, $r0 111 move.d $r0, [$acr] 112 addq 4, $acr 113 move $s1, $r0 114 move.d $r0, [$acr] 115 addq 4, $acr 116 move $s2, $r0 117 move.d $r0, [$acr] 118 addq 4, $acr 119 move $s3, $r0 120 move.d $r0, [$acr] 121 addq 4, $acr 122 move $s4, $r0 123 move.d $r0, [$acr] 124 addq 4, $acr 125 move $s5, $r0 126 move.d $r0, [$acr] 127 addq 4, $acr 128 move $s6, $r0 129 move.d $r0, [$acr] 130 addq 4, $acr 131 move $s7, $r0 132 move.d $r0, [$acr] 133 addq 4, $acr 134 move $s8, $r0 135 move.d $r0, [$acr] 136 addq 4, $acr 137 move $s9, $r0 138 move.d $r0, [$acr] 139 addq 4, $acr 140 move $s10, $r0 141 move.d $r0, [$acr] 142 addq 4, $acr 143 move $s11, $r0 144 move.d $r0, [$acr] 145 addq 4, $acr 146 move $s12, $r0 147 move.d $r0, [$acr] 148 addq 4, $acr 149 150 ;; Nothing in S13 - S15, bank 0 151 clear.d [$acr] 152 addq 4, $acr 153 clear.d [$acr] 154 addq 4, $acr 155 clear.d [$acr] 156 addq 4, $acr 157 158;; Bank 1 and bank 2 have the same layout, hence the loop. 159 addq 1, $r1 1601: 161 move $r1, $srs 162 nop 163 nop 164 nop 165 move $s0, $r0 166 move.d $r0, [$acr] 167 addq 4, $acr 168 move $s1, $r0 169 move.d $r0, [$acr] 170 addq 4, $acr 171 move $s2, $r0 172 move.d $r0, [$acr] 173 addq 4, $acr 174 move $s3, $r0 175 move.d $r0, [$acr] 176 addq 4, $acr 177 move $s4, $r0 178 move.d $r0, [$acr] 179 addq 4, $acr 180 move $s5, $r0 181 move.d $r0, [$acr] 182 addq 4, $acr 183 move $s6, $r0 184 move.d $r0, [$acr] 185 addq 4, $acr 186 187 ;; Nothing in S7 - S15, bank 1 and 2 188 clear.d [$acr] 189 addq 4, $acr 190 clear.d [$acr] 191 addq 4, $acr 192 clear.d [$acr] 193 addq 4, $acr 194 clear.d [$acr] 195 addq 4, $acr 196 clear.d [$acr] 197 addq 4, $acr 198 clear.d [$acr] 199 addq 4, $acr 200 clear.d [$acr] 201 addq 4, $acr 202 clear.d [$acr] 203 addq 4, $acr 204 clear.d [$acr] 205 addq 4, $acr 206 207 addq 1, $r1 208 cmpq 3, $r1 209 bne 1b 210 nop 211 212;; Bank 3 213 move $r1, $srs 214 nop 215 nop 216 nop 217 move $s0, $r0 218 move.d $r0, [$acr] 219 addq 4, $acr 220 move $s1, $r0 221 move.d $r0, [$acr] 222 addq 4, $acr 223 move $s2, $r0 224 move.d $r0, [$acr] 225 addq 4, $acr 226 move $s3, $r0 227 move.d $r0, [$acr] 228 addq 4, $acr 229 move $s4, $r0 230 move.d $r0, [$acr] 231 addq 4, $acr 232 move $s5, $r0 233 move.d $r0, [$acr] 234 addq 4, $acr 235 move $s6, $r0 236 move.d $r0, [$acr] 237 addq 4, $acr 238 move $s7, $r0 239 move.d $r0, [$acr] 240 addq 4, $acr 241 move $s8, $r0 242 move.d $r0, [$acr] 243 addq 4, $acr 244 move $s9, $r0 245 move.d $r0, [$acr] 246 addq 4, $acr 247 move $s10, $r0 248 move.d $r0, [$acr] 249 addq 4, $acr 250 move $s11, $r0 251 move.d $r0, [$acr] 252 addq 4, $acr 253 move $s12, $r0 254 move.d $r0, [$acr] 255 addq 4, $acr 256 move $s13, $r0 257 move.d $r0, [$acr] 258 addq 4, $acr 259 move $s14, $r0 260 move.d $r0, [$acr] 261 addq 4, $acr 262;; Nothing in S15, bank 3 263 clear.d [$acr] 264 addq 4, $acr 265 266;; Check what got us here: get IDX field of EXS. 267 move $exs, $r10 268 and.d 0xff00, $r10 269 lsrq 8, $r10 270#if defined(CONFIG_ETRAX_KGDB_PORT0) 271 cmp.d SER0_INTR_VECT, $r10 ; IRQ for serial port 0 272 beq sigint 273 nop 274#elif defined(CONFIG_ETRAX_KGDB_PORT1) 275 cmp.d SER1_INTR_VECT, $r10 ; IRQ for serial port 1 276 beq sigint 277 nop 278#elif defined(CONFIG_ETRAX_KGDB_PORT2) 279 cmp.d SER2_INTR_VECT, $r10 ; IRQ for serial port 2 280 beq sigint 281 nop 282#elif defined(CONFIG_ETRAX_KGDB_PORT3) 283 cmp.d SER3_INTR_VECT, $r10 ; IRQ for serial port 3 284 beq sigint 285 nop 286#endif 287;; Multiple interrupt must be due to serial break. 288 cmp.d 0x30, $r10 ; Multiple interrupt 289 beq sigint 290 nop 291;; Neither of those? Then it's a sigtrap. 292 ba handle_comm 293 moveq 5, $r10 ; Set SIGTRAP (delay slot) 294 295sigint: 296 ;; Serial interrupt; get character 297 jsr getDebugChar 298 nop ; Delay slot 299 cmp.b 3, $r10 ; \003 (Ctrl-C)? 300 bne return ; No, get out of here 301 nop 302 moveq 2, $r10 ; Set SIGINT 303 304;; 305;; Handle the communication 306;; 307handle_comm: 308 move.d internal_stack+1020, $sp ; Use the internal stack which grows upwards 309 jsr handle_exception ; Interactive routine 310 nop 311 312;; 313;; Return to the caller 314;; 315return: 316 317;; First of all, write the support registers. 318 clear.d $r1 ; Bank counter 319 move.d sreg, $acr 320 321;; Bank 0 322 move $r1, $srs 323 nop 324 nop 325 nop 326 move.d [$acr], $r0 327 move $r0, $s0 328 addq 4, $acr 329 move.d [$acr], $r0 330 move $r0, $s1 331 addq 4, $acr 332 move.d [$acr], $r0 333 move $r0, $s2 334 addq 4, $acr 335 move.d [$acr], $r0 336 move $r0, $s3 337 addq 4, $acr 338 move.d [$acr], $r0 339 move $r0, $s4 340 addq 4, $acr 341 move.d [$acr], $r0 342 move $r0, $s5 343 addq 4, $acr 344 345;; Nothing in S6 - S7, bank 0. 346 addq 4, $acr 347 addq 4, $acr 348 349 move.d [$acr], $r0 350 move $r0, $s8 351 addq 4, $acr 352 move.d [$acr], $r0 353 move $r0, $s9 354 addq 4, $acr 355 move.d [$acr], $r0 356 move $r0, $s10 357 addq 4, $acr 358 move.d [$acr], $r0 359 move $r0, $s11 360 addq 4, $acr 361 move.d [$acr], $r0 362 move $r0, $s12 363 addq 4, $acr 364 365;; Nothing in S13 - S15, bank 0 366 addq 4, $acr 367 addq 4, $acr 368 addq 4, $acr 369 370;; Bank 1 and bank 2 have the same layout, hence the loop. 371 addq 1, $r1 3722: 373 move $r1, $srs 374 nop 375 nop 376 nop 377 move.d [$acr], $r0 378 move $r0, $s0 379 addq 4, $acr 380 move.d [$acr], $r0 381 move $r0, $s1 382 addq 4, $acr 383 move.d [$acr], $r0 384 move $r0, $s2 385 addq 4, $acr 386 387;; S3 (MM_CAUSE) is read-only. 388 addq 4, $acr 389 390 move.d [$acr], $r0 391 move $r0, $s4 392 addq 4, $acr 393 394;; FIXME: Actually write S5/S6? (Affects MM_CAUSE.) 395 addq 4, $acr 396 addq 4, $acr 397 398;; Nothing in S7 - S15, bank 1 and 2 399 addq 4, $acr 400 addq 4, $acr 401 addq 4, $acr 402 addq 4, $acr 403 addq 4, $acr 404 addq 4, $acr 405 addq 4, $acr 406 addq 4, $acr 407 addq 4, $acr 408 409 addq 1, $r1 410 cmpq 3, $r1 411 bne 2b 412 nop 413 414;; Bank 3 415 move $r1, $srs 416 nop 417 nop 418 nop 419 move.d [$acr], $r0 420 move $r0, $s0 421 addq 4, $acr 422 move.d [$acr], $r0 423 move $r0, $s1 424 addq 4, $acr 425 move.d [$acr], $r0 426 move $r0, $s2 427 addq 4, $acr 428 move.d [$acr], $r0 429 move $r0, $s3 430 addq 4, $acr 431 move.d [$acr], $r0 432 move $r0, $s4 433 addq 4, $acr 434 move.d [$acr], $r0 435 move $r0, $s5 436 addq 4, $acr 437 move.d [$acr], $r0 438 move $r0, $s6 439 addq 4, $acr 440 move.d [$acr], $r0 441 move $r0, $s7 442 addq 4, $acr 443 move.d [$acr], $r0 444 move $r0, $s8 445 addq 4, $acr 446 move.d [$acr], $r0 447 move $r0, $s9 448 addq 4, $acr 449 move.d [$acr], $r0 450 move $r0, $s10 451 addq 4, $acr 452 move.d [$acr], $r0 453 move $r0, $s11 454 addq 4, $acr 455 move.d [$acr], $r0 456 move $r0, $s12 457 addq 4, $acr 458 move.d [$acr], $r0 459 move $r0, $s13 460 addq 4, $acr 461 move.d [$acr], $r0 462 move $r0, $s14 463 addq 4, $acr 464 465;; Nothing in S15, bank 3 466 addq 4, $acr 467 468;; Now, move on to the regular register restoration process. 469 470 move.d reg, $acr ; Reset ACR to point at the beginning of the register image 471 move.d [$acr], $r0 ; Restore R0 472 addq 4, $acr 473 move.d [$acr], $r1 ; Restore R1 474 addq 4, $acr 475 move.d [$acr], $r2 ; Restore R2 476 addq 4, $acr 477 move.d [$acr], $r3 ; Restore R3 478 addq 4, $acr 479 move.d [$acr], $r4 ; Restore R4 480 addq 4, $acr 481 move.d [$acr], $r5 ; Restore R5 482 addq 4, $acr 483 move.d [$acr], $r6 ; Restore R6 484 addq 4, $acr 485 move.d [$acr], $r7 ; Restore R7 486 addq 4, $acr 487 move.d [$acr], $r8 ; Restore R8 488 addq 4, $acr 489 move.d [$acr], $r9 ; Restore R9 490 addq 4, $acr 491 move.d [$acr], $r10 ; Restore R10 492 addq 4, $acr 493 move.d [$acr], $r11 ; Restore R11 494 addq 4, $acr 495 move.d [$acr], $r12 ; Restore R12 496 addq 4, $acr 497 move.d [$acr], $r13 ; Restore R13 498 499;; 500;; We restore all registers, even though some of them probably haven't changed. 501;; 502 503 addq 4, $acr 504 move.d [$acr], $sp ; Restore SP (R14) 505 506 ;; ACR cannot be restored just yet. 507 addq 8, $acr 508 509 ;; Skip BZ, VR. 510 addq 2, $acr 511 512 move [$acr], $pid ; Restore PID 513 addq 4, $acr 514 move [$acr], $srs ; Restore SRS 515 nop 516 nop 517 nop 518 addq 1, $acr 519 520 ;; Skip WZ. 521 addq 2, $acr 522 523 move [$acr], $exs ; Restore EXS. 524 addq 4, $acr 525 move [$acr], $eda ; Restore EDA. 526 addq 4, $acr 527 move [$acr], $mof ; Restore MOF. 528 529 ;; Skip DZ. 530 addq 8, $acr 531 532 move [$acr], $ebp ; Restore EBP. 533 addq 4, $acr 534 move [$acr], $erp ; Restore ERP. 535 addq 4, $acr 536 move [$acr], $srp ; Restore SRP. 537 addq 4, $acr 538 move [$acr], $nrp ; Restore NRP. 539 addq 4, $acr 540 move [$acr], $ccs ; Restore CCS like an ordinary register. 541 addq 4, $acr 542 move [$acr], $usp ; Restore USP 543 addq 4, $acr 544 move [$acr], $spc ; Restore SPC 545 ; No restoration of pseudo-PC of course. 546 547 move.d reg, $acr ; Reset ACR to point at the beginning of the register image 548 add.d 15*4, $acr 549 move.d [$acr], $acr ; Finally, restore ACR. 550 rete ; Same as jump ERP 551 rfe ; Shifts CCS 552