root/arch/ppc/kernel/head.S

/* [previous][next][first][last][top][bottom][index][help] */
   1 #include "ppc_asm.tmpl"
   2 #include "ppc_defs.h"
   3 
   4 #define SYNC() \
   5         isync; \
   6         sync
   7 
   8 /* #define TLB_STATS /* Trace TLB exceptions */
   9 
  10 /* Keep track of low-level exceptions - rather crude, but informative */        
  11 #define STATS
  12 
  13 /*
  14  * Increment a [64 bit] statistic counter
  15  * Uses R2, R3
  16  */
  17 #define BUMP(ctr) /*\
  18         lis     r2,ctr@h; \
  19         ori     r2,r2,ctr@l; \
  20         lwz     r3,4(r2); \
  21         addic   r3,r3,1; \
  22         stw     r3,4(r2); \
  23         lwz     r3,0(r2); \
  24         addze   r3,r3; \
  25         stw     r3,0(r2)*/
  26 
  27 /* The same as 'BUMP' but running unmapped (TLB code) */        
  28 #define BUMP_UNMAPPED(ctr) /*\
  29         mfspr   r0,XER; \
  30         lis     r2,ctr@h; \
  31         ori     r2,r2,ctr@l; \
  32         lis     r3,0xF000; \
  33         andc    r2,r2,r3; \
  34         lwz     r3,4(r2); \
  35         addic   r3,r3,1; \
  36         stw     r3,4(r2); \
  37         lwz     r3,0(r2); \
  38         addze   r3,r3; \
  39         mtspr   XER,r0; \
  40         stw     r3,0(r2)*/
  41 
  42 /* These macros can be used to generate very raw traces of low-level */
  43 /* operations (where printf, etc. can't help).  All they provide is */
  44 /* some after-the-fact documentation of what took place.  Since [in */
  45 /* most instances] they have no registers to work with, they use the */
  46 /* hardware "special" registers SPRx for storage.  Because of this, */
  47 /* defining more than one of them simultaneously will yield incorrect */
  48 /* results and a non-functional system.  Note: the trick here is to */
  49 /* gather some data without disturbing anything - Heisenberg are you watching? */
  50 
  51 /* CAUTION! Don't turn on more than one of these at once! */    
  52 /* #define DO_TRAP_TRACE   */
  53 /* #define DO_TLB_TRACE    */
  54 /* #define DO_RFI_TRACE   */
  55 
  56 #ifdef DO_RFI_TRACE
  57 #define DO_RFI_TRACE_UNMAPPED(mark) \
  58         mtspr   SPR0,r1; \
  59         mtspr   SPR1,r2; \
  60         mtspr   SPR2,r3; \
  61         mfcr    r3; \
  62         mtspr   SPR3,r3; \
  63         lis     r1,_RFI_ptr@h; \
  64         ori     r1,r1,_RFI_ptr@l; \
  65         lis     r3,0xF000; \
  66         andc    r1,r1,r3; \
  67         lwz     r1,0(r1); \
  68         andc    r1,r1,r3; \
  69         subi    r1,r1,4; \
  70         lis     r2,(mark>>16); \
  71         ori     r2,r2,(mark&0xFFFF); \
  72         stwu    r2,4(r1); \
  73         mfspr   r2,SRR0; \
  74         stwu    r2,4(r1); \
  75         mfspr   r2,SRR1; \
  76         stwu    r2,4(r1); \
  77         addi    r1,r1,4+4; \
  78         lis     r2,_RFI_ptr@h; \
  79         ori     r2,r2,_RFI_ptr@l; \
  80         andc    r2,r2,r3; \
  81         stw     r1,0(r2); \
  82         mfspr   r3,SPR3; \
  83         mtcrf   0xFF,r3; \
  84         mfspr   r1,SPR0; \
  85         mfspr   r2,SPR1; \
  86         mfspr   r3,SPR2
  87 #define DO_RFI_TRACE_MAPPED(mark) \
  88         mtspr   SPR0,r1; \
  89         mtspr   SPR1,r2; \
  90         mtspr   SPR2,r3; \
  91         mfcr    r3; \
  92         mtspr   SPR3,r3; \
  93         lis     r1,_RFI_ptr@h; \
  94         ori     r1,r1,_RFI_ptr@l; \
  95         lwz     r1,0(r1); \
  96         lis     r3,0x9000; \
  97         or      r1,r1,r3; \
  98         subi    r1,r1,4; \
  99         lis     r2,(mark>>16); \
 100         ori     r2,r2,(mark&0xFFFF); \
 101         stwu    r2,4(r1); \
 102         mfspr   r2,SRR0; \
 103         stwu    r2,4(r1); \
 104         mfspr   r2,SRR1; \
 105         stwu    r2,4(r1); \
 106         addi    r1,r1,4+4; \
 107         lis     r2,_RFI_ptr@h; \
 108         ori     r2,r2,_RFI_ptr@l; \
 109         stw     r1,0(r2); \
 110         mfspr   r3,SPR3; \
 111         mtcrf   0xFF,r3; \
 112         mfspr   r1,SPR0; \
 113         mfspr   r2,SPR1; \
 114         mfspr   r3,SPR2
 115 #else
 116 #define DO_RFI_TRACE_UNMAPPED(mark)
 117 #define DO_RFI_TRACE_MAPPED(mark)
 118 #endif
 119 
 120 #ifdef DO_TRAP_TRACE
 121 #define DEFAULT_TRAP(offset) \
 122         mtspr   SPR0,r1; \
 123         mtspr   SPR1,r2; \
 124         mtspr   SPR2,r3; \
 125         lis     r1,_TRAP_ptr@h; \
 126         ori     r1,r1,_TRAP_ptr@l; \
 127         lis     r3,0xF000; \
 128         andc    r1,r1,r3; \
 129         lwz     r1,0(r1); \
 130         andc    r1,r1,r3; \
 131         subi    r1,r1,4; \
 132         lis     r2,0xCACA; \
 133         ori     r2,r2,offset; \
 134         stwu    r2,4(r1); \
 135         mfspr   r2,SRR0; \
 136         stwu    r2,4(r1); \
 137         mfspr   r2,SRR1; \
 138         stwu    r2,4(r1); \
 139         mfspr   r2,SPR0; \
 140         stwu    r2,4(r1); \
 141         addi    r1,r1,4; \
 142         lis     r2,_TRAP_ptr@h; \
 143         ori     r2,r2,_TRAP_ptr@l; \
 144         andc    r2,r2,r3; \
 145         stw     r1,0(r2); \
 146         mfspr   r1,SPR0; \
 147         mfspr   r2,SPR1; \
 148         mfspr   r3,SPR2; \
 149         li      r13,0; \
 150         ori     r13,r13,HID0_ICE; \
 151         mtspr   HID0,r13; \
 152         lis     r13,0xFFF00000>>16; \
 153         ori     r13,r13,offset; \
 154         mtlr    r13; \
 155         b       hang
 156 #define TRACE_TRAP(offset) \
 157         mtspr   SPR0,r1; \
 158         mtspr   SPR1,r2; \
 159         mtspr   SPR2,r3; \
 160         mfcr    r3; \
 161         mtspr   SPR3,r3; \
 162         lis     r1,_TRAP_ptr@h; \
 163         ori     r1,r1,_TRAP_ptr@l; \
 164         lis     r3,0xF000; \
 165         andc    r1,r1,r3; \
 166         lwz     r1,0(r1); \
 167         andc    r1,r1,r3; \
 168         subi    r1,r1,4; \
 169         lis     r2,0xCABB; \
 170         ori     r2,r2,offset; \
 171         stwu    r2,4(r1); \
 172         dcbst   0,r1; \
 173         mfspr   r2,SRR0; \
 174         stwu    r2,4(r1); \
 175         dcbst   0,r1; \
 176         mfspr   r2,SRR1; \
 177         stwu    r2,4(r1); \
 178         dcbst   0,r1; \
 179         li      r2,offset; \
 180         cmpi    0,r2,0x0C00; \
 181         beq     01f; \
 182         cmpi    0,r2,0x0300; \
 183         beq     00f; \
 184         cmpi    0,r2,0x0400; \
 185         beq     00f; \
 186         mfspr   r2,SPR0; \
 187         b       02f; \
 188 00:     mfspr   r2,DAR; \
 189         b       02f; \
 190 01:     mr      r2,r0; \
 191 02:     stwu    r2,4(r1); \
 192         dcbst   0,r1; \
 193         addi    r1,r1,4; \
 194         mflr    r2; \
 195         stw     r2,0(r1); \
 196         bl      check_trace; \
 197         lwz     r2,0(r1); \
 198         mtlr    r2; \
 199 02:     lis     r2,_TRAP_ptr@h; \
 200         ori     r2,r2,_TRAP_ptr@l; \
 201         oris    r1,r1,0x9000; \
 202         cmp     0,r1,r2; \
 203         bne     00f; \
 204         lis     r1,_TRAP_TRACE@h; \
 205         ori     r1,r1,_TRAP_TRACE@l; \
 206 00:     lis     r3,0xF000; \
 207         andc    r2,r2,r3; \
 208         stw     r1,0(r2); \
 209         mfspr   r1,SPR0; \
 210         mfspr   r2,SPR1; \
 211         mfspr   r3,SPR3; \
 212         mtcrf   0xFF,r3; \
 213         mfspr   r3,SPR2
 214 #else
 215 #define DEFAULT_TRAP(offset) \
 216         li      r13,0; \
 217         ori     r13,r13,HID0_ICE; \
 218         mtspr   HID0,r13; \
 219         lis     r13,0xFFF00000>>16; \
 220         ori     r13,r13,offset; \
 221         mtlr    r13; \
 222         blr
 223 #define TRACE_TRAP(offset)      
 224 #endif
 225 
 226 #define DATA_CACHE_OFF() \
 227         mfspr   r2,HID0; \
 228         li      r3,0; \
 229         ori     r3,r3,HID0_DCE; \
 230         andc    r2,r2,r3; \
 231         mtspr   HID0,r2;
 232 
 233 #define DATA_CACHE_ON() \
 234         mfspr   r2,HID0; \
 235         ori     r2,r2,HID0_DCE; \
 236         mtspr   HID0,r2;
 237 
 238 /* This instruction is not implemented on the PPC 603 */
 239 #define tlbia \
 240         li      r4,32; \
 241         mtspr   CTR,r4; \
 242         lis     r4,0x9000; \
 243 0:      tlbie   r4; \
 244         addi    r4,r4,0x1000; \
 245         bdnz    0b
 246 
 247 /* Validate kernel stack - check for overflow */
 248 #define CHECK_STACK()
 249 #define _CHECK_STACK()\
 250         mtspr   SPR0,r3; \
 251         lis     r2,current@ha; \
 252         lwz     r2,current@l(r2); \
 253         lwz     r2,KERNEL_STACK_PAGE(r2); \
 254         lis     r3,sys_stack@h; \
 255         ori     r3,r3,sys_stack@l; \
 256         cmpl    0,r1,r3; \
 257         ble     02f; \
 258         li      r3,0x0FFF; \
 259         andc    r2,r2,r3; \
 260         andc    r3,r1,r3; \
 261         cmp     0,r3,r2; \
 262         beq     02f; \
 263         mr      r3,r1; \
 264         bl      _EXTERN(bad_stack); \
 265 02:     mfspr   r3,SPR0
 266 
 267 /* Save all registers on kernel stack during an exception */    
 268 #define SAVE_REGS(mark) \
 269         subi    r1,r1,INT_FRAME_SIZE;   /* Make room for frame */ \
 270         stmw    r3,GPR3(r1);    /* Save R3..R31 */ \
 271         stw     r3,ORIG_GPR3(r1); \
 272         stw     r0,GPR0(r1); \
 273         mfspr   r2,SPR0; \
 274         stw     r2,GPR1(r1); \
 275         mfspr   r2,SPR1; \
 276         stw     r2,GPR2(r1); \
 277         mfspr   r2,SPR2; \
 278         stw     r2,_NIP(r1); \
 279         mfspr   r2,SPR3; \
 280         stw     r2,_MSR(r1); \
 281         mfctr   r2; \
 282         stw     r2,_CTR(r1); \
 283         mflr    r2; \
 284         stw     r2,_LINK(r1); \
 285         mfcr    r2; \
 286         stw     r2,_CCR(r1); \
 287         mfspr   r2,XER; \
 288         stw     r2,_XER(r1); \
 289         stfd    fr0,FPR0(r1); \
 290         stfd    fr1,FPR1(r1); \
 291         stfd    fr2,FPR2(r1); \
 292         stfd    fr3,FPR3(r1); \
 293         mffs    fr0; \
 294         stfd    fr0,FPCSR(r1); \
 295         lis     r2,_break_lwarx@h; \
 296         ori     r2,r2,_break_lwarx@l; \
 297         stwcx.  r2,0,r2; \
 298         li      r2,mark; \
 299         stw     r2,TRAP(r1); \
 300         lis     r2,0xDEAD; \
 301         ori     r2,r2,0xDEAD; \
 302         stw     r2,MARKER(r1); \
 303         li      r2,0; \
 304         stw     r2,RESULT(r1)
 305 
 306 #define SAVE_PAGE_FAULT_REGS(offset) \
 307         mfspr   r2,DAR; \
 308         stw     r2,_DAR(r1); \
 309         mfspr   r2,DSISR; \
 310         stw     r2,_DSISR(r1); \
 311         mfspr   r2,HASH1; \
 312         stw     r2,_HASH1(r1); \
 313         mfspr   r2,HASH2; \
 314         stw     r2,_HASH2(r1); \
 315         mfspr   r2,IMISS; \
 316         stw     r2,_IMISS(r1); \
 317         mfspr   r2,DMISS; \
 318         stw     r2,_DMISS(r1); \
 319         mfspr   r2,ICMP; \
 320         stw     r2,_ICMP(r1); \
 321         mfspr   r2,DCMP; \
 322         stw     r2,_DCMP(r1)
 323         
 324 #define SAVE_INT_REGS(mark) \
 325         mtspr   SPR0,r1;        /* Save current stack pointer */ \
 326         mtspr   SPR1,r2;        /* Scratch */ \
 327         mfcr    r2; \
 328         mtspr   SPR2,r2; \
 329         mfspr   r2,SRR1;        /* Interrupt from user/system mode */ \
 330         andi.   r2,r2,MSR_PR; \
 331         beq+    10f;            /* Jump if system - already have stack */ \
 332         mfspr   r2,SPR2;        /* Restore CCR */ \
 333         mtcrf   0xFF,r2; \
 334         mfspr   r2,SRR0;        /* Preserve interrupt registers */ \
 335         mtspr   SPR2,r2; \
 336         mfspr   r2,SRR1; \
 337         mtspr   SPR3,r2; \
 338         lis     r2,05f@h; \
 339         ori     r2,r2,05f@l; \
 340         mtspr   SRR0,r2; \
 341         mfmsr   r2; \
 342         ori     r2,r2,MSR_|MSR_DR|MSR_IR; \
 343         mtspr   SRR1,r2; \
 344         rfi; \
 345 05:     lis     r2,current@ha; \
 346         lwz     r2,current@l(r2); \
 347         mfspr   r1,SPR2; \
 348         stw     r1,TSS+LAST_PC(r2); \
 349         lwz     r1,TSS+KSP(r2); \
 350         b       20f; \
 351 10:     mfspr   r2,SPR2;        /* Restore CCR */ \
 352         mtcrf   0xFF,r2; \
 353         mfspr   r2,SRR0;        /* Preserve interrupt registers */ \
 354         mtspr   SPR2,r2; \
 355         mfspr   r2,SRR1; \
 356         mtspr   SPR3,r2; \
 357         lis     r2,20f@h; \
 358         ori     r2,r2,20f@l; \
 359         mtspr   SRR0,r2; \
 360         mfmsr   r2; \
 361         ori     r2,r2,MSR_|MSR_DR|MSR_IR; \
 362         mtspr   SRR1,r2; \
 363         SYNC(); \
 364         rfi; \
 365 20:   SAVE_REGS(mark); \
 366         CHECK_STACK()
 367 
 368 #define RETURN_FROM_INT(mark) \
 369 90:     mfmsr   r0;             /* Disable interrupts */ \
 370         li      r4,0; \
 371         ori     r4,r4,MSR_EE; \
 372         andc    r0,r0,r4; \
 373         mtmsr   r0; \
 374         SYNC(); \
 375         lis     r2,intr_count@ha; /* Need to run 'bottom half' */ \
 376         lwz     r3,intr_count@l(r2); \
 377         cmpi    0,r3,0; \
 378         bne     00f; \
 379         lis     r4,bh_mask@ha; \
 380         lwz     r4,bh_mask@l(r4); \
 381         lis     r5,bh_active@ha; \
 382         lwz     r5,bh_active@l(r5); \
 383         and.    r4,r4,r5; \
 384         beq     00f; \
 385         addi    r3,r3,1; \
 386         stw     r3,intr_count@l(r2); \
 387         bl      _EXTERN(_do_bottom_half); \
 388         lis     r2,intr_count@ha; \
 389         lwz     r3,intr_count@l(r2); \
 390         subi    r3,r3,1; \
 391         stw     r3,intr_count@l(r2); \
 392 00:     lwz     r2,_MSR(r1); /* Returning to user mode? */ \
 393         andi.   r2,r2,MSR_PR; \
 394         beq+    10f;            /* no - no need to mess with stack */ \
 395         lis     r2,kernel_pages_are_copyback@ha; \
 396         lwz     r2,kernel_pages_are_copyback@l(r2); \
 397         cmpi    0,r2,0; \
 398         beq     05f; \
 399         bl      _EXTERN(flush_instruction_cache); \
 400 05:     lis     r3,current@ha;  /* need to save kernel stack pointer */ \
 401         lwz     r3,current@l(r3); \
 402         addi    r4,r1,INT_FRAME_SIZE;   /* size of frame */ \
 403         stw     r4,TSS+KSP(r3); \
 404         lwz     r4,STATE(r3);   /* If state != 0, can't run */ \
 405         cmpi    0,r4,0; \
 406         beq     06f; \
 407         bl      _EXTERN(schedule); \
 408         b       90b; \
 409 06:     lwz     r4,COUNTER(r3); /* Time quantum expired? */ \
 410         cmpi    0,r4,0; \
 411         bne     07f; \
 412         bl      _EXTERN(schedule); \
 413         b       90b; \
 414 07:     lwz     r4,BLOCKED(r3); /* Check for pending unblocked signals */ \
 415         lwz     r5,SIGNAL(r3); \
 416         andc.   r0,r5,r4;       /* Lets thru any unblocked */ \
 417         beq     10f; \
 418         mr      r3,r4; \
 419         mr      r4,r1; \
 420         bl      _EXTERN(do_signal); \
 421 10:     lwz     r2,_NIP(r1);    /* Restore environment */ \
 422         mtspr   SRR0,r2; \
 423         lwz     r2,_MSR(r1); \
 424         mtspr   SRR1,r2; \
 425         lmw     r3,GPR3(r1); \
 426         lwz     r2,_CTR(r1); \
 427         mtctr   r2; \
 428         lwz     r2,_LINK(r1); \
 429         mtlr    r2; \
 430         lwz     r2,_XER(r1); \
 431         mtspr   XER,r2; \
 432         lwz     r2,_CCR(r1); \
 433         mtcrf   0xFF,r2; \
 434         lfd     fr0,FPCSR(r1); \
 435         mtfsf   0xFF,fr0; \
 436         lfd     fr0,FPR0(r1); \
 437         lfd     fr1,FPR1(r1); \
 438         lfd     fr2,FPR2(r1); \
 439         lfd     fr3,FPR3(r1); \
 440         lwz     r0,GPR0(r1); \
 441         lwz     r2,GPR2(r1); \
 442         lwz     r1,GPR1(r1); \
 443         SYNC(); \
 444         rfi
 445 
 446 _TEXT()
 447         .globl  _start
 448 _start:
 449         .globl  _stext
 450 _stext:
 451 
 452 hang:
 453         ori     r0,r0,0
 454         b       hang
 455         
 456 _ORG(0x0100)
 457 
 458 /* Hard Reset */
 459         .globl  HardReset
 460 HardReset:
 461         b       Reset
 462 
 463 _ORG(0x0200)
 464         b       MachineCheck
 465 
 466 _ORG(0x0300)
 467         b       DataAccess
 468 
 469 _ORG(0x0400)
 470         b       InstructionAccess
 471 
 472 _ORG(0x0500)
 473         b       HardwareInterrupt
 474         
 475 _ORG(0x0600)
 476         b       Alignment
 477 
 478 _ORG(0x0700)
 479         b       ProgramCheck
 480 
 481 _ORG(0x0800)
 482         b       FloatingPointCheck
 483 
 484 /* Decrementer register - ignored for now... */
 485 _ORG(0x0900)
 486 /* TRACE_TRAP(0x900) */
 487         mtspr   SPR0,r1
 488         lis     r1,0x7FFF
 489         ori     r1,r1,0xFFFF
 490         mtspr   DEC,r1
 491         mfspr   r1,SPR0
 492 #if 0   
 493         SYNC
 494 #endif  
 495         rfi
 496         
 497 _ORG(0x0A00)
 498 DEFAULT_TRAP(0x0A00)    
 499 _ORG(0x0B00)
 500 DEFAULT_TRAP(0x0B00)
 501 
 502 /*
 503  * System call
 504  */
 505 _ORG(0x0C00)
 506         b       SystemCall
 507 
 508 _ORG(0x0D00)
 509 DEFAULT_TRAP(0x0D00)    
 510 _ORG(0x0E00)
 511 DEFAULT_TRAP(0x0E00)    
 512 _ORG(0x0F00)
 513 DEFAULT_TRAP(0x0F00)    
 514 
 515 /*
 516  * Handle TLB Miss on an instruction load
 517  */
 518 _ORG(0x1000)
 519 /* Note: It is *unsafe* to use the TRACE TRAP macro here since there */
 520 /* could be a 'trace' in progress when the TLB miss occurs.          */
 521 /* TRACE_TRAP(0x1000) */
 522 #ifdef TLB_STATS
 523         lis     r2,DataLoadTLB_trace_ptr@h
 524         ori     r2,r2,DataLoadTLB_trace_ptr@l
 525         lis     r3,0xF000
 526         andc    r2,r2,r3
 527         lwz     r1,0(r2)
 528         andc    r1,r1,r3
 529         li      r0,0x1000
 530         stw     r0,0(r1)
 531         mftbu   r0
 532         stw     r0,4(r1)
 533         mftb    r0
 534         stw     r0,8(r1)
 535         mfspr   r0,IMISS
 536         mfspr   r3,SRR1
 537         extrwi  r3,r3,1,14
 538         or      r0,r0,r3
 539         stw     r0,12(r1)
 540         addi    r1,r1,16
 541         mfcr    r0
 542         cmpl    0,r1,r2
 543         blt     00f
 544         lis     r1,DataLoadTLB_trace_buf@h
 545         ori     r1,r1,DataLoadTLB_trace_buf@l
 546         lis     r3,0xF000
 547         andc    r1,r1,r3
 548 00:     mtcrf   0xFF,r0
 549         stw     r1,0(r2)
 550 #endif  
 551         b       InstructionTLBMiss
 552 
 553 /*
 554  * Handle TLB Miss on a data item load
 555  */
 556 _ORG(0x1100)
 557 /* TRACE_TRAP(0x1100) */
 558 #ifdef TLB_STATS
 559         lis     r2,DataLoadTLB_trace_ptr@h
 560         ori     r2,r2,DataLoadTLB_trace_ptr@l
 561         lis     r3,0xF000
 562         andc    r2,r2,r3
 563         lwz     r1,0(r2)
 564         andc    r1,r1,r3
 565         li      r0,0x1100
 566         stw     r0,0(r1)
 567         mftbu   r0
 568         stw     r0,4(r1)
 569         mftb    r0
 570         stw     r0,8(r1)
 571         mfspr   r0,DMISS
 572         mfspr   r3,SRR1
 573         extrwi  r3,r3,1,14
 574         or      r0,r0,r3
 575         stw     r0,12(r1)
 576         addi    r1,r1,16
 577         mfcr    r0
 578         cmpl    0,r1,r2
 579         blt     00f
 580         lis     r1,DataLoadTLB_trace_buf@h
 581         ori     r1,r1,DataLoadTLB_trace_buf@l
 582         lis     r3,0xF000
 583         andc    r1,r1,r3
 584 00:     mtcrf   0xFF,r0
 585         stw     r1,0(r2)
 586         .data
 587 DataLoadTLB_trace_buf:
 588         .space  64*1024*4
 589 DataLoadTLB_trace_ptr:
 590         .long   DataLoadTLB_trace_buf
 591         .text
 592 #endif  
 593         b       DataLoadTLBMiss
 594 
 595 /*
 596  * Handle TLB Miss on a store operation
 597  */
 598 _ORG(0x1200)
 599 /* TRACE_TRAP(0x1200) */
 600 #ifdef TLB_STATS
 601         lis     r2,DataLoadTLB_trace_ptr@h
 602         ori     r2,r2,DataLoadTLB_trace_ptr@l
 603         lis     r3,0xF000
 604         andc    r2,r2,r3
 605         lwz     r1,0(r2)
 606         andc    r1,r1,r3
 607         li      r0,0x1200
 608         stw     r0,0(r1)
 609         mftbu   r0
 610         stw     r0,4(r1)
 611         mftb    r0
 612         stw     r0,8(r1)
 613         mfspr   r0,DMISS
 614         mfspr   r3,SRR1
 615         extrwi  r3,r3,1,14
 616         or      r0,r0,r3
 617         stw     r0,12(r1)
 618         addi    r1,r1,16
 619         mfcr    r0
 620         cmpl    0,r1,r2
 621         blt     00f
 622         lis     r1,DataLoadTLB_trace_buf@h
 623         ori     r1,r1,DataLoadTLB_trace_buf@l
 624         lis     r3,0xF000
 625         andc    r1,r1,r3
 626 00:     mtcrf   0xFF,r0
 627         stw     r1,0(r2)
 628 #endif  
 629         b       DataStoreTLBMiss
 630 
 631 _ORG(0x1300)
 632 InstructionAddressBreakpoint:
 633         DEFAULT_TRAP(0x1300)
 634 
 635 _ORG(0x1400)
 636 SystemManagementInterrupt:
 637         DEFAULT_TRAP(0x1400)
 638 
 639 _ORG(0x1500)
 640 
 641 /*
 642  * This space [buffer] is used to forceably flush the data cache when
 643  * running in copyback mode.  This is necessary IFF the data cache could
 644  * contain instructions for which the instruction cache has stale data.
 645  * Since the instruction cache NEVER snoops the data cache, memory must
 646  * be made coherent with the data cache to insure that the instruction
 647  * cache gets a valid instruction stream.  Note that this flushing is
 648  * only performed when switching from system to user mode since this is
 649  * the only juncture [as far as the OS goes] where the data cache may
 650  * contain instructions, e.g. after a disk read.
 651  */
 652 #define NUM_CACHE_LINES 128*2
 653 #define CACHE_LINE_SIZE 32 
 654 cache_flush_buffer:
 655         .space  NUM_CACHE_LINES*CACHE_LINE_SIZE /* CAUTION! these need to match hardware */
 656 
 657 #if NUM_CACHE_LINES < 512       
 658 _ORG(0x4000)
 659 #endif
 660 
 661 /*
 662  * Hardware reset [actually from bootstrap]
 663  * Initialize memory management & call secondary init
 664  */     
 665 Reset:
 666         lis     r7,0xF000               /* To mask upper 4 bits */
 667 /* Copy argument string */
 668         li      r0,0            /* Null terminate string */
 669         stb     r0,0(r12)
 670         lis     r1,cmd_line@h
 671         ori     r1,r1,cmd_line@l
 672         andc    r1,r1,r7        /* No MMU yet - need unmapped address */
 673         subi    r1,r1,1
 674         subi    r11,r11,1
 675 00:     lbzu    r0,1(r11)
 676         cmpi    0,r0,0
 677         stbu    r0,1(r1)
 678         bne     00b     
 679         lis     r1,sys_stack@h
 680         ori     r1,r1,sys_stack@l
 681         li      r2,0x0FFF       /* Mask stack address down to page boundary */
 682         andc    r1,r1,r2
 683         subi    r1,r1,INT_FRAME_SIZE    /* Padding for first frame */
 684         li      r2,0            /* TOC pointer for nanokernel */
 685         li      r0,MSR_         /* Make sure FPU enabled */
 686         mtmsr   r0
 687         lis     r3,_edata@h     /* Clear BSS */
 688         ori     r3,r3,_edata@l
 689         andc    r3,r3,r7        /* make unmapped address */
 690         lis     r4,_end@h
 691         ori     r4,r4,_end@l
 692         andc    r4,r4,r7        /* make unmapped address */
 693         subi    r3,r3,4
 694         li      r0,0
 695 00:     stwu    r0,4(r3)
 696         cmp     0,r3,r4
 697         blt     00b
 698 /* Initialize BAT registers */
 699         lis     r3,BAT0@h
 700         ori     r3,r3,BAT0@l
 701         andc    r3,r3,r7        /* make unmapped address */
 702         lwz     r0,0(r3)
 703         mtspr   IBAT0U,r0
 704         mtspr   DBAT0U,r0
 705         lwz     r0,4(r3)
 706         mtspr   IBAT0L,r0
 707         mtspr   DBAT0L,r0
 708         lis     r3,BAT1@h
 709         ori     r3,r3,BAT1@l
 710         andc    r3,r3,r7        /* make unmapped address */
 711         lwz     r0,0(r3)
 712         mtspr   IBAT1U,r0
 713         mtspr   DBAT1U,r0
 714         lwz     r0,4(r3)
 715         mtspr   IBAT1L,r0
 716         mtspr   DBAT1L,r0
 717         lis     r3,TMP_BAT2@h
 718         ori     r3,r3,TMP_BAT2@l
 719         andc    r3,r3,r7        /* make unmapped address */
 720         lwz     r0,0(r3)
 721         mtspr   IBAT2U,r0
 722         mtspr   DBAT2U,r0
 723         lwz     r0,4(r3)
 724         mtspr   IBAT2L,r0
 725         mtspr   DBAT2L,r0
 726 /* Now we can turn on the MMU */
 727         mfmsr   r3
 728         ori     r3,r3,MSR_DR|MSR_IR
 729         mtspr   SRR1,r3
 730         lis     r3,10f@h
 731         ori     r3,r3,10f@l
 732         mtspr   SRR0,r3
 733 DO_RFI_TRACE_UNMAPPED(0xDEAD0000)       
 734         SYNC
 735         rfi                             /* enables MMU */
 736 10:     bl      _EXTERN(MMU_init)       /* initialize MMU environment */
 737 DO_RFI_TRACE_MAPPED(0xDEAD0100) 
 738 /* Withdraw BAT2->RAM mapping */
 739 #if 1
 740         lis     r7,0xF000               /* To mask upper 4 bits */
 741         lis     r3,20f@h
 742         ori     r3,r3,20f@l
 743         andc    r3,r3,r7        /* make unmapped address */
 744         mtspr   SRR0,r3
 745         mfmsr   r3
 746         li      r4,MSR_DR|MSR_IR
 747         andc    r3,r3,r4
 748         mtspr   SRR1,r3
 749         SYNC
 750 DO_RFI_TRACE_MAPPED(0xDEAD0200) 
 751         SYNC
 752         rfi
 753 20:
 754 DO_RFI_TRACE_UNMAPPED(0xDEAD0400)       
 755 20:     lis     r3,BAT2@h
 756         ori     r3,r3,BAT2@l
 757         andc    r3,r3,r7        /* make unmapped address */
 758         lwz     r0,0(r3)
 759         mtspr   IBAT2U,r0
 760         mtspr   DBAT2U,r0
 761         lwz     r0,4(r3)
 762         mtspr   IBAT2L,r0
 763         mtspr   DBAT2L,r0
 764 #endif
 765 
 766 /* Load up the kernel context */
 767         lis     r2,init_task@h
 768         ori     r2,r2,init_task@l
 769         addi    r2,r2,TSS
 770         andc    r2,r2,r7        /* make unmapped address */
 771         SYNC                    /* Force all PTE updates to finish */
 772         tlbia                   /* Clear all TLB entries */
 773         lis     r3,_SDR1@h
 774         ori     r3,r3,_SDR1@l
 775         andc    r3,r3,r7        /* make unmapped address */
 776         lwz     r3,0(r3)
 777         mtspr   SDR1,r3
 778         lwz     r0,MMU_SEG0(r2)
 779         mtsr    SR0,r0
 780         lwz     r0,MMU_SEG1(r2)
 781         mtsr    SR1,r0
 782         lwz     r0,MMU_SEG2(r2)
 783         mtsr    SR2,r0
 784         lwz     r0,MMU_SEG3(r2)
 785         mtsr    SR3,r0
 786         lwz     r0,MMU_SEG4(r2)
 787         mtsr    SR4,r0
 788         lwz     r0,MMU_SEG5(r2)
 789         mtsr    SR5,r0
 790         lwz     r0,MMU_SEG6(r2)
 791         mtsr    SR6,r0
 792         lwz     r0,MMU_SEG7(r2)
 793         mtsr    SR7,r0
 794         lwz     r0,MMU_SEG8(r2)
 795         mtsr    SR8,r0
 796         lwz     r0,MMU_SEG9(r2)
 797         mtsr    SR9,r0
 798         lwz     r0,MMU_SEG10(r2)
 799         mtsr    SR10,r0
 800         lwz     r0,MMU_SEG11(r2)
 801         mtsr    SR11,r0
 802         lwz     r0,MMU_SEG12(r2)
 803         mtsr    SR12,r0
 804         lwz     r0,MMU_SEG13(r2)
 805         mtsr    SR13,r0
 806         lwz     r0,MMU_SEG14(r2)
 807         mtsr    SR14,r0
 808         lwz     r0,MMU_SEG15(r2)
 809         mtsr    SR15,r0
 810 /* Now turn on the MMU for real! */
 811         mfmsr   r3
 812         ori     r3,r3,MSR_DR|MSR_IR
 813         mtspr   SRR1,r3
 814         lis     r3,30f@h
 815         ori     r3,r3,30f@l
 816         mtspr   SRR0,r3
 817 DO_RFI_TRACE_UNMAPPED(0xDEAD0500)       
 818         SYNC
 819         rfi                             /* enables MMU */
 820 30:
 821 DO_RFI_TRACE_MAPPED(0xDEAD0600)
 822 /* Turn on L1 Data Cache */
 823         mfspr   r3,HID0         /* Caches are controlled by this register */
 824         ori     r4,r3,(HID0_ICE|HID0_ICFI)
 825         ori     r3,r3,(HID0_ICE)
 826         ori     r4,r4,(HID0_DCE|HID0_DCI)
 827         ori     r3,r3,(HID0_DCE)
 828         sync
 829         mtspr   HID0,r4
 830         mtspr   HID0,r3
 831 /* L1 cache enable */   
 832         b       _EXTERN(start_kernel)           /* call main code */
 833         .long   0               # Illegal!
 834 
 835 /*
 836  * Machine Check (Bus Errors, etc)
 837  */
 838 MachineCheck:   
 839         TRACE_TRAP(0x0200)
 840         SAVE_INT_REGS(0x0200)
 841         mr      r3,r1           /* Set pointer to saved regs */
 842         bl      _EXTERN(MachineCheckException)
 843         RETURN_FROM_INT(0x0200)
 844 
 845 /*
 846  * Data Access exception
 847  */
 848 DataAccess:
 849         TRACE_TRAP(0x0300)
 850         SAVE_INT_REGS(0x0300)
 851         SAVE_PAGE_FAULT_REGS(0x0300)
 852         BUMP(__Data_Page_Faults)
 853         mr      r3,r1           /* Set pointer to saved regs */
 854         bl      _EXTERN(DataAccessException)
 855         RETURN_FROM_INT(0x0300)
 856 
 857 /*
 858  * Instruction Access Exception
 859  */
 860 InstructionAccess:
 861         TRACE_TRAP(0x0400)
 862         SAVE_INT_REGS(0x0400)
 863         SAVE_PAGE_FAULT_REGS(0x0400)
 864         BUMP(__Instruction_Page_Faults)
 865         mr      r3,r1           /* Set pointer to saved regs */
 866         bl      _EXTERN(InstructionAccessException)
 867         bl      _EXTERN(flush_instruction_cache)
 868         RETURN_FROM_INT(0x0400)
 869 
 870 /*
 871  * Hardware Interrupt
 872  */
 873 HardwareInterrupt:      
 874         SAVE_INT_REGS(0x0500)
 875         BUMP(__Hardware_Interrupts)
 876         mr      r3,r1           /* Set pointer to saved regs */
 877         bl      _EXTERN(handle_IRQ)
 878         RETURN_FROM_INT(0x0500)
 879 
 880 /*
 881  * Alignment
 882  */
 883 Alignment:      
 884         TRACE_TRAP(0x0600)
 885         SAVE_INT_REGS(0x0600)
 886         mr      r3,r1           /* Set pointer to saved regs */
 887         bl      _EXTERN(AlignmentException)
 888         RETURN_FROM_INT(0x0600)
 889 
 890 /*
 891  * Illegal instruction
 892  */
 893 ProgramCheck:
 894         TRACE_TRAP(0x0700)
 895         SAVE_INT_REGS(0x0700)
 896         mr      r3,r1           /* Set pointer to saved regs */
 897         bl      _EXTERN(ProgramCheckException)
 898         RETURN_FROM_INT(0x0700)
 899 
 900 /*
 901  * Floating point [not available, etc]
 902  */
 903 FloatingPointCheck:     
 904         TRACE_TRAP(0x0800)
 905         SAVE_INT_REGS(0x0800)
 906         mr      r3,r1           /* Set pointer to saved regs */
 907         bl      _EXTERN(FloatingPointCheckException)
 908         RETURN_FROM_INT(0x0200)
 909 
 910 /*
 911  * System Call exception
 912  */     
 913 SystemCall:
 914         SAVE_INT_REGS(0x0C00)
 915         lwz     r2,_CCR(r1)     /* Clear SO bit in CR */
 916         lis     r9,0x1000
 917         andc    r2,r2,r9
 918         stw     r2,_CCR(r1)
 919         cmpi    0,r0,0x7777     /* Special case for 'sys_sigreturn' */
 920         bne+    10f
 921         mr      r3,r1
 922         bl      _EXTERN(sys_sigreturn)
 923         cmpi    0,r3,0          /* Check for restarted system call */
 924         bge     99f
 925         b       20f
 926 10:     lis     r2,sys_call_table@h
 927         ori     r2,r2,sys_call_table@l
 928         slwi    r0,r0,2
 929         lwzx    r2,r2,r0        /* Fetch system call handler [ptr] */
 930  
 931         mtlr    r2
 932         mr      r9,r1
 933         blrl                    /* Call handler */
 934 20:     stw     r3,RESULT(r1)   /* Save result */       
 935         cmpi    0,r3,0
 936         bge     30f
 937         neg     r3,r3
 938         lwz     r2,_CCR(r1)     /* Set SO bit in CR */
 939         oris    r2,r2,0x1000
 940         stw     r2,_CCR(r1)
 941 30:     stw     r3,GPR3(r1)     /* Update return value */
 942 99:
 943         RETURN_FROM_INT(0x0C00)
 944 
 945 /*
 946  * Handle TLB miss for instruction
 947  */
 948 InstructionTLBMiss:
 949         BUMP_UNMAPPED(__Instruction_TLB_Misses)
 950 #ifdef DO_TLB_TRACE
 951         lis     r1,_TLB_ptr@h
 952         ori     r1,r1,_TLB_ptr@l
 953         lis     r2,0xF000
 954         andc    r1,r1,r2
 955         lwz     r1,0(r1)
 956         andc    r1,r1,r2
 957         subi    r1,r1,4
 958         lis     r2,0xBEBE
 959         ori     r2,r2,0x0100
 960         stwu    r2,4(r1)
 961         mfspr   r2,SRR0
 962         stwu    r2,4(r1)
 963         mfspr   r2,SRR1
 964         stwu    r2,4(r1)
 965         mfspr   r2,HASH1
 966         stwu    r2,4(r1)
 967         mfspr   r2,HASH2
 968         stwu    r2,4(r1)
 969         mfspr   r2,ICMP
 970         stwu    r2,4(r1)
 971         mfspr   r2,IMISS
 972         stwu    r2,4(r1)
 973         addi    r1,r1,4+(1*4)
 974         lis     r3,_TLB_ptr@h
 975         ori     r3,r3,_TLB_ptr@l
 976         lis     r2,0xF000
 977         andc    r3,r3,r2
 978         stw     r1,0(r3)
 979 #endif  
 980         mfctr   r0              /* Need to save this - CTR can't be touched! */
 981         mfspr   r2,HASH1        /* Get PTE pointer */
 982         mfspr   r3,ICMP         /* Partial item compare value */
 983 00:     li      r1,8            /* 8 items / bucket */
 984         mtctr   r1
 985         subi    r2,r2,8         /* Preset pointer */
 986 10:     lwzu    r1,8(r2)        /* Get next PTE */
 987         cmp     0,r1,r3         /* Found entry yet? */
 988         bdne    10b             /* Jump back if not, until CTR==0 */
 989         bne     30f             /* Try secondary hash if CTR==0 */
 990         lwz     r1,4(r2)        /* Get second word of entry */
 991 #if 0   
 992         andi.   r3,r1,0x08      /* Check guard bit - invalid access if set */
 993         bne     InstructionFetchError
 994 #endif  
 995         andi.   r3,r1,0x100     /* Check R bit (referenced) */
 996         bne     20f             /* If set, all done */
 997         ori     r1,r1,0x100     /* Set bit */
 998         stw     r1,4(r2)        /* Update memory image */
 999 20:     mtctr   r0              /* Restore CTR */
1000         mfspr   r3,SRR1         /* Need to restore CR0 */
1001         mtcrf   0x80,r3
1002         mfspr   r0,IMISS        /* Set to update TLB */
1003         mtspr   RPA,r1
1004         tlbli   r0
1005 #if 0   
1006         SYNC
1007 #endif
1008         rfi                     /* All done */
1009 /* Secondary hash */
1010 30:     andi.   r1,r3,0x40      /* Already doing secondary hash? */
1011         bne     InstructionAddressInvalid /* Yes - item not in hash table */
1012         mfspr   r2,HASH2        /* Get hash table pointer */
1013         ori     r3,r3,0x40      /* Set secondary hash */
1014         b       00b                     /* Try lookup again */
1015 
1016 /*
1017  * Handle TLB miss for DATA Load operation
1018  */     
1019 DataLoadTLBMiss:
1020         BUMP_UNMAPPED(__DataLoad_TLB_Misses)
1021 #ifdef DO_TLB_TRACE
1022         lis     r1,_TLB_ptr@h
1023         ori     r1,r1,_TLB_ptr@l
1024         lis     r2,0xF000
1025         andc    r1,r1,r2
1026         lwz     r1,0(r1)
1027         andc    r1,r1,r2
1028         subi    r1,r1,4
1029         lis     r2,0xBEBE
1030         ori     r2,r2,0x0200
1031         stwu    r2,4(r1)
1032         mfspr   r2,SRR0
1033         stwu    r2,4(r1)
1034         mfspr   r2,SRR1
1035         stwu    r2,4(r1)
1036         mfspr   r2,HASH1
1037         stwu    r2,4(r1)
1038         mfspr   r2,HASH2
1039         stwu    r2,4(r1)
1040         mfspr   r2,DCMP
1041         stwu    r2,4(r1)
1042         mfspr   r2,DMISS
1043         stwu    r2,4(r1)
1044         addi    r1,r1,4+(1*4)
1045         lis     r3,_TLB_ptr@h
1046         ori     r3,r3,_TLB_ptr@l
1047         lis     r2,0xF000
1048         andc    r3,r3,r2
1049         stw     r1,0(r3)
1050 #endif  
1051         mfctr   r0              /* Need to save this - CTR can't be touched! */
1052         mfspr   r2,HASH1        /* Get PTE pointer */
1053         mfspr   r3,DCMP         /* Partial item compare value */
1054 00:     li      r1,8            /* 8 items / bucket */
1055         mtctr   r1
1056         subi    r2,r2,8         /* Preset pointer */
1057 10:     lwzu    r1,8(r2)        /* Get next PTE */
1058         cmp     0,r1,r3         /* Found entry yet? */
1059         bdne    10b             /* Jump back if not, until CTR==0 */
1060         bne     30f             /* Try secondary hash if CTR==0 */
1061         lwz     r1,4(r2)        /* Get second word of entry */
1062         andi.   r3,r1,0x100     /* Check R bit (referenced) */
1063         ori     r1,r1,0x100     /* Set bit */
1064         bne     20f             /* If set, all done */
1065         stw     r1,4(r2)        /* Update memory image */
1066 20:     mtctr   r0              /* Restore CTR */
1067         mfspr   r3,SRR1         /* Need to restore CR0 */
1068         mtcrf   0x80,r3
1069         mfspr   r0,DMISS        /* Set to update TLB */
1070         mtspr   RPA,r1
1071 /*      SYNC() */
1072         tlbld   r0
1073 #if 0   
1074         SYNC
1075 #endif  
1076         rfi                     /* All done */
1077 /* Secondary hash */
1078 30:     andi.   r1,r3,0x40      /* Already doing secondary hash? */
1079         bne     DataAddressInvalid /* Yes - item not in hash table */
1080         mfspr   r2,HASH2        /* Get hash table pointer */
1081         ori     r3,r3,0x40      /* Set secondary hash */
1082         b       00b                     /* Try lookup again */
1083 
1084 /*
1085  * Handle TLB miss for DATA STORE
1086  */
1087 DataStoreTLBMiss:
1088         BUMP_UNMAPPED(__DataStore_TLB_Misses)
1089 #ifdef DO_TLB_TRACE
1090         lis     r1,_TLB_ptr@h
1091         ori     r1,r1,_TLB_ptr@l
1092         lis     r2,0xF000
1093         andc    r1,r1,r2
1094         lwz     r1,0(r1)
1095         andc    r1,r1,r2
1096         subi    r1,r1,4
1097         lis     r2,0xBEBE
1098         ori     r2,r2,0x0300
1099         stwu    r2,4(r1)
1100         mfspr   r2,SRR0
1101         stwu    r2,4(r1)
1102         mfspr   r2,SRR1
1103         stwu    r2,4(r1)
1104         mfspr   r2,HASH1
1105         stwu    r2,4(r1)
1106         mfspr   r2,HASH2
1107         stwu    r2,4(r1)
1108         mfspr   r2,DCMP
1109         stwu    r2,4(r1)
1110         mfspr   r2,DMISS
1111         stwu    r2,4(r1)
1112         addi    r1,r1,4+(1*4)
1113         lis     r3,_TLB_ptr@h
1114         ori     r3,r3,_TLB_ptr@l
1115         lis     r2,0xF000
1116         andc    r3,r3,r2
1117         stw     r1,0(r3)
1118 #endif  
1119         mfctr   r0              /* Need to save this - CTR can't be touched! */
1120         mfspr   r2,HASH1        /* Get PTE pointer */
1121         mfspr   r3,DCMP         /* Partial item compare value */
1122 00:     li      r1,8            /* 8 items / bucket */
1123         mtctr   r1
1124         subi    r2,r2,8         /* Preset pointer */
1125 10:     lwzu    r1,8(r2)        /* Get next PTE */
1126         cmp     0,r1,r3         /* Found entry yet? */
1127         bdne    10b             /* Jump back if not, until CTR==0 */
1128         bne     30f             /* Try secondary hash if CTR==0 */
1129         lwz     r1,4(r2)        /* Get second word of entry */
1130         andi.   r3,r1,0x80      /* Check C bit (changed) */
1131 #if 0 /* Note: no validation */
1132         beq     40f             /* If not set (first time) validate access */
1133 #else
1134         ori     r1,r1,0x180     /* Set changed, accessed */
1135         bne     20f
1136         stw     r1,4(r2)
1137 #endif  
1138 20:     mtctr   r0              /* Restore CTR */
1139         mfspr   r3,SRR1         /* Need to restore CR0 */
1140         mtcrf   0x80,r3
1141         mfspr   r0,DMISS        /* Set to update TLB */
1142         mtspr   RPA,r1
1143         tlbld   r0
1144 #if 0   
1145         SYNC
1146 #endif  
1147         rfi                     /* All done */  
1148 /* Secondary hash */
1149 30:     andi.   r1,r3,0x40      /* Already doing secondary hash? */
1150         bne     DataAddressInvalid /* Yes - item not in hash table */
1151         mfspr   r2,HASH2        /* Get hash table pointer */
1152         ori     r3,r3,0x40      /* Set secondary hash */
1153         b       00b                     /* Try lookup again */
1154 /* PTE found - validate access */
1155 40:     rlwinm. r3,r1,30,0,1    /* Extract PP bits */
1156         bge-    50f             /* Jump if PP=0,1 */
1157         andi.   r3,r1,1
1158         beq+    70f             /* Access OK */
1159         b       WriteProtectError       /* Not OK - fail! */
1160 50:     mfspr   r3,SRR1         /* Check privilege */
1161         andi.   r3,r3,MSR_PR
1162         beq+    60f             /* Jump if supervisor mode */
1163         mfspr   r3,DMISS        /* Get address */
1164         mfsrin  r3,r3           /* Get segment register */
1165         andis.  r3,r3,0x2000    /* If Kp==0, OK */
1166         beq+    70f
1167         b       WriteProtectError       /* Bad access */
1168 60:     mfspr   r3,DMISS        /* Get address */
1169         mfsrin  r3,r3           /* Get segment register */
1170         andis.  r3,r3,0x4000    /* If Ks==0, OK */
1171         beq+    70f
1172         b       WriteProtectError       /* Bad access */
1173 70:     ori     r1,r1,0x180     /* Set changed, accessed */
1174         stw     r1,4(r2)        /* Update PTE in memory */
1175         b       20b
1176         
1177 /*
1178  * These routines are error paths/continuations of the exception
1179  * handlers above.  They are placed here to avoid the problems
1180  * of only 0x100 bytes per exception handler.
1181  */
1182  
1183 /* Invalid address */
1184 InstructionAddressInvalid:
1185         mfspr   r3,SRR1
1186         rlwinm  r1,r3,9,6,6     /* Get load/store bit */
1187         addis   r1,r1,0x4000    /* Set bit 1 -> PTE not found */
1188         b       10f
1189 
1190 /* Fetch from guarded or no-access page */
1191 InstructionFetchError:
1192         mfspr   r3,SRR1
1193         rlwinm  r1,r3,9,6,6     /* Get load/store bit */
1194         addis   r1,r1,0x0800    /* Set bit 4 -> protection error */
1195 10:     mtspr   DSISR,r1
1196         mtctr   r0              /* Restore CTR */
1197         andi.   r2,r3,0xFFFF    /* Clear upper bits of SRR1 */
1198         mtspr   SRR1,r2
1199         mfspr   r1,IMISS        /* Get failing address */
1200         rlwinm. r2,r2,0,31,31   /* Check for little endian access */
1201         beq     20f             /* Jump if big endian */
1202         xori    r1,r1,3
1203 20:     mtspr   DAR,r1          /* Set fault address */
1204         mfmsr   r0              /* Restore "normal" registers */
1205         xoris   r0,r0,MSR_TGPR>>16
1206         mtcrf   0x80,r3         /* Restore CR0 */
1207         ori     r0,r0,MSR_FP    /* Need to keep FP enabled */
1208         mtmsr   r0
1209         b       InstructionAccess
1210 
1211 /* Invalid address */
1212 DataAddressInvalid:
1213         mfspr   r3,SRR1
1214         rlwinm  r1,r3,9,6,6     /* Get load/store bit */
1215         addis   r1,r1,0x4000    /* Set bit 1 -> PTE not found */
1216         b       10f
1217 
1218 /* Write to read-only space */
1219 WriteProtectError:
1220         mfspr   r3,SRR1
1221         rlwinm  r1,r3,9,6,6     /* Get load/store bit */
1222         addis   r1,r1,0x0800    /* Set bit 4 -> protection error */
1223 10:     mtspr   DSISR,r1
1224         mtctr   r0              /* Restore CTR */
1225         andi.   r2,r3,0xFFFF    /* Clear upper bits of SRR1 */
1226         mtspr   SRR1,r2
1227         mfspr   r1,DMISS        /* Get failing address */
1228         rlwinm. r2,r2,0,31,31   /* Check for little endian access */
1229         beq     20f             /* Jump if big endian */
1230         xori    r1,r1,3
1231 20:     mtspr   DAR,r1          /* Set fault address */
1232         mfmsr   r0              /* Restore "normal" registers */
1233         xoris   r0,r0,MSR_TGPR>>16
1234         mtcrf   0x80,r3         /* Restore CR0 */
1235         ori     r0,r0,MSR_FP    /* Need to keep FP enabled */
1236         mtmsr   r0
1237         b       DataAccess
1238 
1239 /*
1240  * Flush instruction cache
1241  * *** I'm really paranoid here!
1242  */
1243 _GLOBAL(flush_instruction_cache)
1244         mflr    r5
1245         bl      _EXTERN(flush_data_cache)
1246         mfspr   r3,HID0 /* Caches are controlled by this register */
1247         li      r4,0
1248         ori     r4,r4,(HID0_ICE|HID0_ICFI)
1249         andc    r3,r3,r4
1250         isync
1251         mtspr   HID0,r3         /* Disable cache */
1252         isync
1253         ori     r3,r3,HID0_ICFI
1254         isync
1255         mtspr   HID0,r3         /* Invalidate cache */
1256         isync
1257         andc    r3,r3,r4
1258         isync
1259         mtspr   HID0,r3         /* Invalidate (step 2) */
1260         isync
1261         ori     r3,r3,HID0_ICE
1262         isync
1263         mtspr   HID0,r3         /* Enable cache */
1264         isync
1265         mtlr    r5
1266         blr
1267 
1268 /*
1269  * Flush data cache
1270  * *** I'm really paranoid here!
1271  */
1272 _GLOBAL(flush_data_cache)
1273         BUMP(__Cache_Flushes)
1274         lis     r3,cache_is_copyback@ha
1275         lwz     r3,cache_is_copyback@l(r3)
1276         cmpi    0,r3,0
1277         beq     10f
1278 /* When DATA CACHE is copy-back */
1279         lis     r3,cache_flush_buffer@h
1280         ori     r3,r3,cache_flush_buffer@l
1281         li      r4,NUM_CACHE_LINES
1282         mtctr   r4
1283 00:     dcbz    0,r3                    /* Flush cache line with minimal BUS traffic */
1284         addi    r3,r3,CACHE_LINE_SIZE   /* Next line, please */
1285         bdnz    00b     
1286 10:     blr
1287         
1288 /*
1289  * This routine switches between two different tasks.  The process
1290  * state of one is saved on it's kernel stack.  Then the state
1291  * of the other is restored from it's kernel stack.  The memory
1292  * management hardware is updated to the second processes's state.
1293  * Finally, we can return to the second process, via the 'return'.
1294  *
1295  * Note: there are two ways to get to the "going out" portion
1296  * of this code; either by coming in via the entry (_switch)
1297  * or via "fork" which must set up an environment equivalent
1298  * to the "_switch" path.  If you change this (or in particular, the
1299  * SAVE_REGS macro), you'll have to change the fork code also.
1300  *
1301  * The code which creates the new task context is in 'copy_thread'
1302  * in arch/ppc/kernel/process.c
1303  */     
1304 _GLOBAL(_switch)
1305         mtspr   SPR0,r1         /* SAVE_REGS prologue */
1306         mtspr   SPR1,r2
1307         mflr    r2              /* Return to switch caller */
1308         mtspr   SPR2,r2
1309         mfmsr   r2
1310         mtspr   SPR3,r2
1311         SAVE_REGS(0x0FF0)
1312         SYNC()
1313         stw     r1,KSP(r3)      /* Set old stack pointer */
1314         BUMP(__Context_Switches)
1315         lwz     r1,KSP(r4)      /* Load new stack pointer */
1316         CHECK_STACK()
1317         lwz     r0,MMU_SEG0(r4)
1318         mtsr    SR0,r0
1319         lwz     r0,MMU_SEG1(r4)
1320         mtsr    SR1,r0
1321         lwz     r0,MMU_SEG2(r4)
1322         mtsr    SR2,r0
1323         lwz     r0,MMU_SEG3(r4)
1324         mtsr    SR3,r0
1325         lwz     r0,MMU_SEG4(r4)
1326         mtsr    SR4,r0
1327         lwz     r0,MMU_SEG5(r4)
1328         mtsr    SR5,r0
1329         lwz     r0,MMU_SEG6(r4)
1330         mtsr    SR6,r0
1331         lwz     r0,MMU_SEG7(r4)
1332         mtsr    SR7,r0
1333         lwz     r0,MMU_SEG8(r4)
1334         mtsr    SR8,r0
1335         lwz     r0,MMU_SEG9(r4)
1336         mtsr    SR9,r0
1337         lwz     r0,MMU_SEG10(r4)
1338         mtsr    SR10,r0
1339         lwz     r0,MMU_SEG11(r4)
1340         mtsr    SR11,r0
1341         lwz     r0,MMU_SEG12(r4)
1342         mtsr    SR12,r0
1343         lwz     r0,MMU_SEG13(r4)
1344         mtsr    SR13,r0
1345         lwz     r0,MMU_SEG14(r4)
1346         mtsr    SR14,r0
1347         lwz     r0,MMU_SEG15(r4)
1348         mtsr    SR15,r0
1349         tlbia                           /* Invalidate entire TLB */
1350         BUMP(__TLBIAs)
1351 #ifdef TLB_STATS
1352 /* TEMP */
1353         lis     r2,DataLoadTLB_trace_ptr@h
1354         ori     r2,r2,DataLoadTLB_trace_ptr@l
1355         lis     r3,0x9000
1356         lwz     r4,0(r2)
1357         or      r4,r4,r3
1358         li      r0,0
1359         stw     r0,0(r4)
1360         stw     r0,4(r4)
1361         stw     r0,8(r4)
1362         stw     r0,12(r4)
1363         addi    r4,r4,4
1364         cmpl    0,r4,r2
1365         blt     00f
1366         lis     r4,DataLoadTLB_trace_buf@h
1367         ori     r4,r4,DataLoadTLB_trace_buf@l
1368 00:     stw     r4,0(r2)
1369 /* TEMP */      
1370 #endif
1371         lwz     r2,_NIP(r1)     /* Force TLB/MMU hit */
1372         lwz     r2,0(r2)
1373         RETURN_FROM_INT(0xF000)
1374         
1375 
1376 /*
1377  * This routine is just here to keep GCC happy - sigh...
1378  */     
1379 _GLOBAL(__main)
1380         blr
1381 
1382 #ifdef DO_TRAP_TRACE
1383 check_trace:
1384         sync                            /* Force all writes out */
1385         lwz     r2,-8(r1)
1386         andi.   r2,r2,MSR_PR
1387         bne     99f
1388         lwz     r2,-32(r1)
1389         lwz     r3,-16(r1)
1390         cmp     0,r2,r3
1391         bne     99f
1392         andi.   r2,r2,0x7FFF
1393         cmpi    0,r2,0x0C00
1394         bge     99f
1395         lwz     r2,-32+4(r1)
1396         lwz     r3,-16+4(r1)
1397         cmp     0,r2,r3
1398         bne     99f
1399         lwz     r2,-32+8(r1)
1400         lwz     r3,-16+8(r1)
1401         cmp     0,r2,r3
1402         bne     99f
1403         lwz     r2,-32(r1)
1404         lwz     r3,-16(r1)
1405         cmp     0,r2,r3
1406         bne     99f
1407         andi.   r2,r2,0x7FFF
1408         cmpi    0,r2,0x0600
1409         beq     00f
1410         lwz     r2,-32+12(r1)
1411         lwz     r3,-16+12(r1)
1412         cmp     0,r2,r3
1413         bne     99f
1414 00:     li      r2,0x7653
1415         stw     r2,0(r1)
1416         b       00b
1417 99:     blr
1418 #endif  
1419 
1420         .data
1421         .globl  sdata
1422 sdata:
1423         .space  2*4096
1424 sys_stack:
1425 
1426         .globl  empty_zero_page
1427 empty_zero_page:
1428         .space  4096
1429 
1430 /*
1431  * This space gets a copy of optional info passed to us by the bootstrap
1432  * Used to pass parameters into the kernel like root=/dev/sda1, etc.
1433  */     
1434         .globl  cmd_line
1435 cmd_line:
1436         .space  512     
1437 
1438 #ifdef STATS    
1439 /*
1440  * Miscellaneous statistics - gathered just for performance info
1441  */
1442 
1443         .globl  _INTR_stats
1444 _INTR_stats:
1445 __Instruction_TLB_Misses:
1446         .long   0,0     /* Instruction TLB misses */
1447 __DataLoad_TLB_Misses:
1448         .long   0,0     /* Data [load] TLB misses */
1449 __DataStore_TLB_Misses:
1450         .long   0,0     /* Data [store] TLB misses */
1451 __Instruction_Page_Faults:      
1452         .long   0,0     /* Instruction page faults */
1453 __Data_Page_Faults:     
1454         .long   0,0     /* Data page faults */
1455 __Cache_Flushes:        
1456         .long   0,0     /* Explicit cache flushes */
1457 __Context_Switches:     
1458         .long   0,0     /* Context switches */
1459 __Hardware_Interrupts:  
1460         .long   0,0     /* I/O interrupts (disk, timer, etc) */
1461         .globl  __TLBIAs
1462 __TLBIAs:
1463         .long   0,0     /* TLB cache forceably flushed */
1464         .globl  __TLBIEs
1465 __TLBIEs:
1466         .long   0,0     /* Specific TLB entry flushed */        
1467 #endif
1468 
1469 /*
1470  * This location is used to break any outstanding "lock"s when
1471  * changing contexts.
1472  */
1473 _break_lwarx:   .long   0
1474 
1475 /*
1476  * Various trace buffers
1477  */     
1478 #ifdef DO_TRAP_TRACE
1479         .data
1480 _TRAP_TRACE: .space     32*1024
1481 _TRAP_ptr:   .long      _TRAP_TRACE
1482         .text
1483 #endif
1484 
1485 #ifdef DO_TLB_TRACE
1486         .data
1487 _TLB_TRACE: .space      128*1024
1488 _TLB_ptr:   .long       _TLB_TRACE
1489         .text
1490 #endif
1491 
1492 #ifdef DO_RFI_TRACE
1493         .data
1494 _RFI_DATA: .space       128*1024
1495 _RFI_ptr:  .long        _RFI_DATA
1496         .text   
1497 #endif

/* [previous][next][first][last][top][bottom][index][help] */