Kyle Swenson | 8d8f654 | 2021-03-15 11:02:55 -0600 | [diff] [blame^] | 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 | |
| 13 | kgdb_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 |
| 160 | 1: |
| 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 | |
| 295 | sigint: |
| 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 | ;; |
| 307 | handle_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 | ;; |
| 315 | return: |
| 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 |
| 372 | 2: |
| 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 |