1#include <config.h> 2#include <asm/ppc_defs.h> 3 4/* #include <asm/cache.h> */ 5#include "cache.h" 6#include <asm/ppc4xx.h> 7 8#include "context.h" 9 10#define CONFIG_SYS_DCACHE_SACR_VALUE (0x00000000) 11#define CONFIG_SYS_ICACHE_SACR_VALUE \ 12 (PPC_128MB_SACR_VALUE(CONFIG_SYS_SDRAM_BASE + ( 0 << 20)) | \ 13 PPC_128MB_SACR_VALUE(CONFIG_SYS_SDRAM_BASE + (128 << 20)) | \ 14 PPC_128MB_SACR_VALUE(CONFIG_SYS_FLASH_BASE)) 15 16#define function_prolog(func_name) .text; \ 17 .align 2; \ 18 .globl func_name; \ 19 func_name: 20#define function_epilog(func_name) .type func_name,@function; \ 21 .size func_name,.-func_name 22 23/* We don't want the MMU yet. 24*/ 25#undef MSR_KERNEL 26#define MSR_KERNEL ( MSR_ME ) /* Machine Check */ 27 28#define SYNC \ 29 sync; \ 30 isync 31 32/* 33 * Macros for storing registers into and loading registers from 34 * exception frames. 35 */ 36#define SAVE_GPR(n, base) stw n,GPR0+4*(n)(base) 37#define SAVE_2GPRS(n, base) SAVE_GPR(n, base); SAVE_GPR(n+1, base) 38#define SAVE_4GPRS(n, base) SAVE_2GPRS(n, base); SAVE_2GPRS(n+2, base) 39#define SAVE_8GPRS(n, base) SAVE_4GPRS(n, base); SAVE_4GPRS(n+4, base) 40#define SAVE_10GPRS(n,base) SAVE_8GPRS(n, base); SAVE_2GPRS(n+8, base) 41#define REST_GPR(n, base) lwz n,GPR0+4*(n)(base) 42#define REST_2GPRS(n, base) REST_GPR(n, base); REST_GPR(n+1, base) 43#define REST_4GPRS(n, base) REST_2GPRS(n, base); REST_2GPRS(n+2, base) 44#define REST_8GPRS(n, base) REST_4GPRS(n, base); REST_4GPRS(n+4, base) 45#define REST_10GPRS(n,base) REST_8GPRS(n, base); REST_2GPRS(n+8, base) 46 47/* 48 * GCC sometimes accesses words at negative offsets from the stack 49 * pointer, although the SysV ABI says it shouldn't. To cope with 50 * this, we leave this much untouched space on the stack on exception 51 * entry. 52 */ 53#define STACK_UNDERHEAD 64 54 55/* 56 * Exception entry code. This code runs with address translation 57 * turned off, i.e. using physical addresses. 58 * We assume sprg3 has the physical address of the current 59 * task's thread_struct. 60 */ 61 /* Save: 62 * CR, r0, r1 (sp), r2, r3, r4, r5, r6, r20, r21, r22, r23, 63 * LR, CTR, XER, DAR, SRR0, SRR1 64 */ 65#define EXCEPTION_PROLOG(reg1, reg2) \ 66 mtspr SPRG0,r20; \ 67 mtspr SPRG1,r21; \ 68 mfcr r20; \ 69 subi r21,r1,INT_FRAME_SIZE+STACK_UNDERHEAD; /* alloc exc. frame */\ 70 stw r20,_CCR(r21); /* save registers */ \ 71 stw r22,GPR22(r21); \ 72 stw r23,GPR23(r21); \ 73 mfspr r20,SPRG0; \ 74 stw r20,GPR20(r21); \ 75 mfspr r22,SPRG1; \ 76 stw r22,GPR21(r21); \ 77 mflr r20; \ 78 stw r20,_LINK(r21); \ 79 mfctr r22; \ 80 stw r22,_CTR(r21); \ 81 mfspr r20,XER; \ 82 stw r20,_XER(r21); \ 83 mfspr r20, DAR_DEAR; \ 84 stw r20,_DAR(r21); \ 85 mfspr r22,reg1; \ 86 mfspr r23,reg2; \ 87 stw r0,GPR0(r21); \ 88 stw r1,GPR1(r21); \ 89 stw r2,GPR2(r21); \ 90 stw r1,0(r21);/* back chain */ \ 91 mr r1,r21;/* set new kernel sp */ \ 92 SAVE_4GPRS(3, r21); 93/* 94 * Note: code which follows this uses cr0.eq (set if from kernel), 95 * r21, r22 (SRR0), and r23 (SRR1). 96 */ 97 98/* 99 * Exception vectors. 100 * 101 * The data words for `hdlr' and `int_return' are initialized with 102 * OFFSET values only; they must be relocated first before they can 103 * be used! 104 */ 105#define STD_EXCEPTION(n, label, hdlr) \ 106 . = n; \ 107label: \ 108 EXCEPTION_PROLOG(SRR0, SRR1); \ 109 lwz r3,GOT(transfer_to_handler); \ 110 mtlr r3; \ 111 addi r3,r1,STACK_FRAME_OVERHEAD; \ 112 li r20,MSR_KERNEL; \ 113 rlwimi r20,r23,0,25,25; \ 114 blrl; \ 115.L_ ## label : \ 116 .long hdlr - _start + _START_OFFSET; \ 117 .long int_return - _start + _START_OFFSET 118 119#define CRIT_EXCEPTION(n, label, hdlr) \ 120 . = n; \ 121label: \ 122 EXCEPTION_PROLOG(CSRR0, CSRR1); \ 123 lwz r3,GOT(transfer_to_handler); \ 124 mtlr r3; \ 125 addi r3,r1,STACK_FRAME_OVERHEAD; \ 126 li r20,(MSR_KERNEL & ~(MSR_ME|MSR_DE|MSR_CE)); \ 127 rlwimi r20,r23,0,25,25; \ 128 blrl; \ 129.L_ ## label : \ 130 .long hdlr - _start + _START_OFFSET; \ 131 .long crit_return - _start + _START_OFFSET 132 133#define MCK_EXCEPTION(n, label, hdlr) \ 134 . = n; \ 135label: \ 136 EXCEPTION_PROLOG(MCSRR0, MCSRR1); \ 137 lwz r3,GOT(transfer_to_handler); \ 138 mtlr r3; \ 139 addi r3,r1,STACK_FRAME_OVERHEAD; \ 140 li r20,(MSR_KERNEL & ~(MSR_ME|MSR_DE|MSR_CE)); \ 141 rlwimi r20,r23,0,25,25; \ 142 blrl; \ 143.L_ ## label : \ 144 .long hdlr - _start + _START_OFFSET; \ 145 .long mck_return - _start + _START_OFFSET 146 147 148/*************************************************************************** 149 * 150 * These definitions simplify the ugly declarations necessary for GOT 151 * definitions. 152 * 153 * Stolen from prepboot/bootldr.h, (C) 1998 Gabriel Paubert, [email protected] 154 * 155 * Uses r14 to access the GOT 156 */ 157 158#define START_GOT \ 159 .section ".got2","aw"; \ 160.LCTOC1 = .+32768 161 162#define END_GOT \ 163 .text 164 165#define GET_GOT \ 166 bl 1f ; \ 167 .text 2 ; \ 1680: .long .LCTOC1-1f ; \ 169 .text ; \ 1701: mflr r14 ; \ 171 lwz r0,0b-1b(r14) ; \ 172 add r14,r0,r14 ; 173 174#define GOT_ENTRY(NAME) .L_ ## NAME = . - .LCTOC1 ; .long NAME 175 176#define GOT(NAME) .L_ ## NAME (r14) 177 178/* 179 * Set up GOT: Global Offset Table 180 * 181 * Use r14 to access the GOT 182 */ 183 START_GOT 184 GOT_ENTRY(_GOT2_TABLE_) 185 GOT_ENTRY(_FIXUP_TABLE_) 186 187 GOT_ENTRY(_start) 188 GOT_ENTRY(_start_of_vectors) 189 GOT_ENTRY(_end_of_vectors) 190 GOT_ENTRY(transfer_to_handler) 191 192 GOT_ENTRY(__init_end) 193 GOT_ENTRY(_end) 194 GOT_ENTRY(__bss_start) 195 END_GOT 196 197/* 198 * r3 - 1st arg to board_init(): IMMP pointer 199 * r4 - 2nd arg to board_init(): boot flag 200 */ 201 .text 202version_string: 203 .ascii "RT-Thread 0.4.0" 204 205 . = EXC_OFF_SYS_RESET 206_start_of_vectors: 207 208 /* Critical input. */ 209 CRIT_EXCEPTION(0x100, CritcalInput, UnknownException) 210 CRIT_EXCEPTION(0x200, MachineCheck, MachineCheckException) 211 /* Data Storage exception. */ 212 STD_EXCEPTION(0x300, DataStorage, UnknownException) 213 /* Instruction Storage exception. */ 214 STD_EXCEPTION(0x400, InstStorage, UnknownException) 215 216 . = 0x0500 217ExtInterrupt: 218 /* save current thread stack */ 219 subi r1, r1, STACK_FRAME_SIZE 220 221 /* save registers */ 222 stw r0,GPR0(r1) /* save general purpose registers 0 */ 223 stmw r2,GPR2(r1) /* save general purpose registers 2-31 */ 224 225 mfusprg0 r0 /* save usprg0 */ 226 stw r0,USPRG0(r1) 227 mfcr r0, /* save cr */ 228 stw r0,CR(r1) 229 mfxer r0 /* save xer */ 230 stw r0,XER(r1) 231 mfctr r0 /* save ctr */ 232 stw r0,CTR(r1) 233 mflr r0 /* save lr */ 234 stw r0, LR(r1) 235 236 mfsrr0 r0 /* save SRR0 and SRR1 */ 237 stw r0,SRR0(r1) 238 mfsrr1 r0 239 stw r0,SRR1(r1) 240 241 bl rt_interrupt_enter 242 bl external_interrupt 243 bl rt_interrupt_leave 244 245 /* restore thread context */ 246 lwz r0,SRR1(r1) /* restore SRR1 and SRR0 */ 247 mtsrr1 r0 248 lwz r0,SRR0(r1) 249 mtsrr0 r0 250 251 lwz r0,LR(r1) /* restore lr */ 252 mtlr r0 253 lwz r0,CTR(r1) /* restore ctr */ 254 mtctr r0 255 lwz r0,XER(r1) /* restore xer */ 256 mtxer r0 257 lwz r0,CR(r1) /* restore cr */ 258 mtcr r0 259 lwz r0,USPRG0(r1) /* restore usprg0 */ 260 // mtusprg0 r0 261 262 lmw r2, GPR2(r1) /* restore general register */ 263 lwz r0,GPR0(r1) 264 addi r1, r1, STACK_FRAME_SIZE 265 b rt_hw_systemcall_entry 266 267/* Alignment exception. */ 268 . = 0x600 269Alignment: 270 EXCEPTION_PROLOG(SRR0, SRR1) 271 mfspr r4,DAR 272 stw r4,_DAR(r21) 273 mfspr r5,DSISR 274 stw r5,_DSISR(r21) 275 addi r3,r1,STACK_FRAME_OVERHEAD 276 li r20,MSR_KERNEL 277 rlwimi r20,r23,0,16,16 /* copy EE bit from saved MSR */ 278 lwz r6,GOT(transfer_to_handler) 279 mtlr r6 280 blrl 281.L_Alignment: 282 .long AlignmentException - _start + _START_OFFSET 283 .long int_return - _start + _START_OFFSET 284 285/* Program check exception */ 286 . = 0x700 287ProgramCheck: 288 EXCEPTION_PROLOG(SRR0, SRR1) 289 addi r3,r1,STACK_FRAME_OVERHEAD 290 li r20,MSR_KERNEL 291 rlwimi r20,r23,0,16,16 /* copy EE bit from saved MSR */ 292 lwz r6,GOT(transfer_to_handler) 293 mtlr r6 294 blrl 295.L_ProgramCheck: 296 .long ProgramCheckException - _start + _START_OFFSET 297 .long int_return - _start + _START_OFFSET 298 299 . = 0x0c00 300SystemCall: 301 b rt_hw_systemcall_entry 302 303 . = 0x1000 304PIT: 305 /* save current thread stack */ 306 subi r1, r1, STACK_FRAME_SIZE 307 308 /* save registers */ 309 stw r0,GPR0(r1) /* save general purpose registers 0 */ 310 stmw r2,GPR2(r1) /* save general purpose registers 2-31 */ 311 312 mfusprg0 r0 /* save usprg0 */ 313 stw r0,USPRG0(r1) 314 mfcr r0, /* save cr */ 315 stw r0,CR(r1) 316 mfxer r0 /* save xer */ 317 stw r0,XER(r1) 318 mfctr r0 /* save ctr */ 319 stw r0,CTR(r1) 320 mflr r0 /* save lr */ 321 stw r0, LR(r1) 322 323 mfsrr0 r0 /* save SRR0 and SRR1 */ 324 stw r0,SRR0(r1) 325 mfsrr1 r0 326 stw r0,SRR1(r1) 327 328 bl rt_interrupt_enter 329 bl DecrementerPITException 330 bl rt_interrupt_leave 331 332 /* restore thread context */ 333 lwz r0,SRR1(r1) /* restore SRR1 and SRR0 */ 334 mtsrr1 r0 335 lwz r0,SRR0(r1) 336 mtsrr0 r0 337 338 lwz r0,LR(r1) /* restore lr */ 339 mtlr r0 340 lwz r0,CTR(r1) /* restore ctr */ 341 mtctr r0 342 lwz r0,XER(r1) /* restore xer */ 343 mtxer r0 344 lwz r0,CR(r1) /* restore cr */ 345 mtcr r0 346 lwz r0,USPRG0(r1) /* restore usprg0 */ 347 // mtusprg0 r0 348 349 lmw r2, GPR2(r1) /* restore general register */ 350 lwz r0,GPR0(r1) 351 addi r1, r1, STACK_FRAME_SIZE 352 b rt_hw_systemcall_entry 353 354 STD_EXCEPTION(0x1100, InstructionTLBMiss, UnknownException) 355 STD_EXCEPTION(0x1200, DataTLBMiss, UnknownException) 356 357 CRIT_EXCEPTION(0x2000, DebugBreakpoint, DebugException ) 358 359_end_of_vectors: 360 . = _START_OFFSET 361 362 /* 363 * start and end addresses of the BSS section 364 * they are taken from the linker script 365 */ 366 367 .set START_BSS, __bss_start 368 .set END_BSS, __bss_end 369 370 /* stack top address exported from linker script */ 371 .set STACK_TOP, __stack_top 372 373_start: 374 /*----------------------------------------------------------------------- */ 375 /* Clear and set up some registers. */ 376 /*----------------------------------------------------------------------- */ 377 addi r4,r0,0x0000 378 mtsgr r4 /* Configure guarded attribute for performance. */ 379 mtsler r4 /* Configure endinanness */ 380 mtsu0r r4 /* and compression. */ 381 382 /*------------------------------------------------------------------------ 383 * Initialize vector tables and other registers 384 * set them all to 0. The Interrupt Handler implementation 385 * has to set these registers later on 386 *-----------------------------------------------------------------------*/ 387 mtdcwr r4 388 mtesr r4 /* clear Exception Syndrome Reg */ 389 mttcr r4 /* clear Timer Control Reg */ 390 mtxer r4 /* clear Fixed-Point Exception Reg */ 391 mtevpr r4 /* clear Exception Vector Prefix Reg */ 392 393 addi r4,r0,(0xFFFF-0x10000) /* set r4 to 0xFFFFFFFF (status in the */ 394 /* dbsr is cleared by setting bits to 1) */ 395 mtdbsr r4 /* clear/reset the dbsr */ 396 397 /* Invalidate the i- and d-caches. */ 398 bl invalidate_icache 399 bl invalidate_dcache 400 401 /* Set-up icache cacheability. */ 402 lis r4, CONFIG_SYS_ICACHE_SACR_VALUE@h 403 ori r4, r4, CONFIG_SYS_ICACHE_SACR_VALUE@l 404 mticcr r4 405 isync 406 407 /* Set-up dcache cacheability. */ 408 lis r4, CONFIG_SYS_DCACHE_SACR_VALUE@h 409 ori r4, r4, CONFIG_SYS_DCACHE_SACR_VALUE@l 410 mtdccr r4 411 412 /*----------------------------------------------------------------------- */ 413 /* DMA Status, clear to come up clean */ 414 /*----------------------------------------------------------------------- */ 415 addis r3,r0, 0xFFFF /* Clear all existing DMA status */ 416 ori r3,r3, 0xFFFF 417 mtdcr dmasr, r3 418 419 /* clear the BSS section */ 420 lis r3,START_BSS@h // load start of BSS into r3 421 ori r3,r3,START_BSS@l 422 lis r4,END_BSS@h // load end of BSS into r4 423 ori r4,r4,END_BSS@l 424 sub r4,r4,r3 // calculate length of BSS 425 srwi r4,r4,2 // convert byte-length to word-length 426 li r5,0 // zero r5 427 cmplw 0,r4,r5 // check to see whether length equals 0 428 beql 0,2f // in case of length 0 we're already done 429 subi r3,r3,4 // because of offset start 4 bytes lower 430 mtctr r4 // use word-length of BSS section as counter 4311: /* bss clear start */ 432 stwu r5,4(r3) // zero one word of BSS section 433 bdnz 1b // keep going until BSS is entirely clean 4342: /* bss clear done */ 435 436 /* Set up stack in the linker script defined RAM area */ 437 lis r1, STACK_TOP@h 438 ori r1, r1, STACK_TOP@l 439 440 /* Set up a zeroized stack frame so that backtrace works right */ 441 li r0, 0 442 stwu r0, -4(r1) 443 stwu r0, -4(r1) 444 445 /* 446 * Set up a dummy frame to store reset vector as return address. 447 * this causes stack underflow to reset board. 448 */ 449 stwu r1, -8(r1) /* Save back chain and move SP */ 450 lis r0, RESET_VECTOR@h /* Address of reset vector */ 451 ori r0, r0, RESET_VECTOR@l 452 stwu r1, -8(r1) /* Save back chain and move SP */ 453 stw r0, +12(r1) /* Save return addr (underflow vect) */ 454 455 GET_GOT /* initialize GOT access */ 456 457 /* NEVER RETURNS! */ 458 bl rtthread_startup 459 460/* 461 * Note: code which follows this uses cr0.eq (set if from kernel), 462 * r20(new MSR), r21(trap frame), r22 (SRR0), and r23 (SRR1). 463 */ 464 465/* 466 * This code finishes saving the registers to the exception frame 467 * and jumps to the appropriate handler for the exception. 468 * Register r21 is pointer into trap frame, r1 has new stack pointer. 469 */ 470transfer_to_handler: 471 stw r22,_NIP(r21) 472 lis r22,MSR_POW@h /* clear POW bit */ 473 andc r23,r23,r22 /* use normal power management */ 474 stw r23,_MSR(r21) /* MSC value when the exception returns */ 475 SAVE_GPR(7, r21) 476 SAVE_4GPRS(8, r21) 477 SAVE_8GPRS(12, r21) 478 SAVE_8GPRS(24, r21) 479 mflr r23 /* hdlr/int_return addr immediately follows */ 480 andi. r24,r23,0x3f00 /* get vector offset */ 481 stw r24,TRAP(r21) /* vector address, such as 0x1000 for PIT */ 482 li r22,0 483 stw r22,RESULT(r21) /* clear the sc return value */ 484 mtspr SPRG2,r22 /* r1 is now kernel sp */ 485 lwz r24,0(r23) /* virtual address of hdlr */ 486 lwz r23,4(r23) /* where to go when done */ 487 mtspr SRR0,r24 /* hdlr */ 488 mtspr SRR1,r20 /* MSR_KERNEL with ME enabled */ 489 mtlr r23 /* call hdlr and then return to int_return */ 490 SYNC /* note r3 has address for pt_regs on stack */ 491 rfi /* jump to handler, enable ME */ 492 493int_return: 494 addi r3,r1,STACK_FRAME_OVERHEAD 495 lwz r4,_MQ(r1) 496 cmpwi r4, 0 497 beq goon_return 498switch_stack: 499 subi r1,r4,STACK_FRAME_OVERHEAD 500goon_return: 501 mfmsr r28 /* Disable interrupts */ 502 li r4,0 503 ori r4,r4,MSR_EE /* clear External Interrupt Enable */ 504 ori r4,r4,MSR_DE /* clear Debug Interrupts Enable - 4xx */ 505 andc r28,r28,r4 506 SYNC /* Some chip revs need this... */ 507 mtmsr r28 508 SYNC 509 lwz r2,_CTR(r1) 510 lwz r0,_LINK(r1) 511 mtctr r2 512 mtlr r0 513 lwz r2,_XER(r1) 514 lwz r0,_CCR(r1) 515 mtspr XER,r2 516 mtcrf 0xFF,r0 517 REST_10GPRS(3, r1) 518 REST_10GPRS(13, r1) 519 REST_8GPRS(23, r1) 520 REST_GPR(31, r1) 521 lwz r2,_NIP(r1) /* Restore environment */ 522 lwz r0,_MSR(r1) 523 mtspr SRR0,r2 524 mtspr SRR1,r0 525 lwz r0,GPR0(r1) 526 lwz r2,GPR2(r1) 527 lwz r1,GPR1(r1) 528 SYNC 529 rfi 530 b . /* prevent prefetch past rfi */ 531 532crit_return: 533 mfmsr r28 /* Disable interrupts */ 534 li r4,0 535 ori r4,r4,MSR_EE 536 andc r28,r28,r4 537 SYNC /* Some chip revs need this... */ 538 mtmsr r28 539 SYNC 540 lwz r2,_CTR(r1) 541 lwz r0,_LINK(r1) 542 mtctr r2 543 mtlr r0 544 lwz r2,_XER(r1) 545 lwz r0,_CCR(r1) 546 mtspr XER,r2 547 mtcrf 0xFF,r0 548 REST_10GPRS(3, r1) 549 REST_10GPRS(13, r1) 550 REST_8GPRS(23, r1) 551 REST_GPR(31, r1) 552 lwz r2,_NIP(r1) /* Restore environment */ 553 lwz r0,_MSR(r1) 554 mtspr SPRN_CSRR0,r2 555 mtspr SPRN_CSRR1,r0 556 lwz r0,GPR0(r1) 557 lwz r2,GPR2(r1) 558 lwz r1,GPR1(r1) 559 SYNC 560 rfci 561 562get_pvr: 563 mfspr r3, PVR 564 blr 565