Prex Home / Browse Source - Prex Version: 0.9.0

root/bsp/hal/ppc/arch/locore.S

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. kernel_start
  2. interrupt_common
  3. syscall_entry
  4. trap_common
  5. cpu_switch
  6. sploff
  7. splon

   1 /*-
   2  * Copyright (c) 2009, Kohsuke Ohtani
   3  * All rights reserved.
   4  *
   5  * Redistribution and use in source and binary forms, with or without
   6  * modification, are permitted provided that the following conditions
   7  * are met:
   8  * 1. Redistributions of source code must retain the above copyright
   9  *    notice, this list of conditions and the following disclaimer.
  10  * 2. Redistributions in binary form must reproduce the above copyright
  11  *    notice, this list of conditions and the following disclaimer in the
  12  *    documentation and/or other materials provided with the distribution.
  13  * 3. Neither the name of the author nor the names of any co-contributors
  14  *    may be used to endorse or promote products derived from this software
  15  *    without specific prior written permission.
  16  *
  17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
  18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  20  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
  21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  27  * SUCH DAMAGE.
  28  */
  29 
  30 /*
  31  * locore.S - low level platform support
  32  */
  33 
  34 /*
  35  * Memo: SPRG usage
  36  *  SPRG0 - kernel stack pointer
  37  *  SPRG1 - saved stack pointer
  38  *  SPRG2 - interrupt nest counter
  39  *  SPRG3 - scratch pad
  40  */
  41 
  42 #include <conf/config.h>
  43 #include <machine/asm.h>
  44 #include <machine/syspage.h>
  45 #include <machine/memory.h>
  46 #include <sys/errno.h>
  47 #include <context.h>
  48 #include <trap.h>
  49 #include <cpu.h>
  50 
  51         .section ".text","ax"
  52 
  53 #define ABS_JUMP(target) \
  54         lis     r12, (target)@ha ; \
  55         ori     r12, r12, (target)@l ; \
  56         mtctr   r12 ;\
  57         bctr
  58 
  59 /*
  60  * Macro to save all registers.
  61  */
  62 #define SAVE_ALL \
  63         subi    r1, r1, CTXREGS; \
  64         stw     r0, REG_R0(r1); \
  65         stw     r2, REG_R2(r1); \
  66         stw     r3, REG_R3(r1); \
  67         stw     r4, REG_R4(r1); \
  68         stw     r5, REG_R5(r1); \
  69         stw     r6, REG_R6(r1); \
  70         stw     r7, REG_R7(r1); \
  71         stw     r8, REG_R8(r1); \
  72         stw     r9, REG_R9(r1); \
  73         stw     r10, REG_R10(r1); \
  74         stw     r11, REG_R11(r1); \
  75         stw     r12, REG_R12(r1); \
  76         stw     r13, REG_R13(r1); \
  77         stw     r14, REG_R14(r1); \
  78         stw     r15, REG_R15(r1); \
  79         stw     r16, REG_R16(r1); \
  80         stw     r17, REG_R17(r1); \
  81         stw     r18, REG_R18(r1); \
  82         stw     r19, REG_R19(r1); \
  83         stw     r20, REG_R20(r1); \
  84         stw     r21, REG_R21(r1); \
  85         stw     r22, REG_R22(r1); \
  86         stw     r23, REG_R23(r1); \
  87         stw     r24, REG_R24(r1); \
  88         stw     r25, REG_R25(r1); \
  89         stw     r26, REG_R26(r1); \
  90         stw     r27, REG_R27(r1); \
  91         stw     r28, REG_R28(r1); \
  92         stw     r29, REG_R29(r1); \
  93         stw     r30, REG_R30(r1); \
  94         stw     r31, REG_R31(r1); \
  95         mfsprg1 r10;                    /* Get saved sp */ \
  96         stw     r10, REG_R1(r1); \
  97         mfspr   r10, SPR_SRR0; \
  98         stw     r10, REG_SRR0(r1); \
  99         mfspr   r10, SPR_SRR1; \
 100         stw     r10, REG_SRR1(r1); \
 101         mfspr   r10, SPR_LR; \
 102         stw     r10, REG_LR(r1); \
 103         mfspr   r10, SPR_CTR; \
 104         stw     r10, REG_CTR(r1); \
 105         mfspr   r10, SPR_XER; \
 106         stw     r10, REG_XER(r1); \
 107         mfspr   r10, SPR_LR; \
 108         stw     r10, REG_LR(r1); \
 109         mfcr    r10; \
 110         stw     r10, REG_CR(r1);
 111 
 112 /*
 113  * Macro to restore all registers.
 114  */
 115 #define RESTORE_ALL \
 116         lwz     r10, REG_SRR0(r1); \
 117         mtspr   SPR_SRR0, r10; \
 118         lwz     r10, REG_SRR1(r1); \
 119         mtspr   SPR_SRR1, r10; \
 120         lwz     r10, REG_LR(r1); \
 121         mtspr   SPR_LR, r10; \
 122         lwz     r10, REG_XER(r1); \
 123         mtspr   SPR_XER, r10; \
 124         lwz     r10, REG_CTR(r1); \
 125         mtspr   SPR_CTR, r10; \
 126         lwz     r10, REG_LR(r1); \
 127         mtspr   SPR_LR, r10; \
 128         lwz     r10, REG_CR(r1); \
 129         mtcr    r10; \
 130         lwz     r10, REG_R1(r1); \
 131         mtsprg1 r10;                    /* Restore saved sp */ \
 132         lwz     r0, REG_R0(r1); \
 133         lwz     r2, REG_R2(r1); \
 134         lwz     r3, REG_R3(r1); \
 135         lwz     r4, REG_R4(r1); \
 136         lwz     r5, REG_R5(r1); \
 137         lwz     r6, REG_R6(r1); \
 138         lwz     r7, REG_R7(r1); \
 139         lwz     r8, REG_R8(r1); \
 140         lwz     r9, REG_R9(r1); \
 141         lwz     r10, REG_R10(r1); \
 142         lwz     r11, REG_R11(r1); \
 143         lwz     r12, REG_R12(r1); \
 144         lwz     r13, REG_R13(r1); \
 145         lwz     r14, REG_R14(r1); \
 146         lwz     r15, REG_R15(r1); \
 147         lwz     r16, REG_R16(r1); \
 148         lwz     r17, REG_R17(r1); \
 149         lwz     r18, REG_R18(r1); \
 150         lwz     r19, REG_R19(r1); \
 151         lwz     r20, REG_R20(r1); \
 152         lwz     r21, REG_R21(r1); \
 153         lwz     r22, REG_R22(r1); \
 154         lwz     r23, REG_R23(r1); \
 155         lwz     r24, REG_R24(r1); \
 156         lwz     r25, REG_R25(r1); \
 157         lwz     r26, REG_R26(r1); \
 158         lwz     r27, REG_R27(r1); \
 159         lwz     r28, REG_R28(r1); \
 160         lwz     r29, REG_R29(r1); \
 161         lwz     r30, REG_R30(r1); \
 162         lwz     r31, REG_R31(r1);
 163 
 164 /*
 165  * Macro to build an exception entry.
 166  * We assume interrupts are disabled.
 167  */
 168 #define EXCEPTION_ENTRY(offset, name, id, xfer) \
 169         .skip offset - (. - exception_vector); \
 170 exception_##name: \
 171         mtsprg1 r1;             /* sprg1: current sp */ \
 172         mtsprg3 r10;            /* sprg3: saved r10 */ \
 173         mfcr    r10;            /* r10: saved cr */ \
 174         mfsrr1  r1;             /* Get msr */ \
 175         mtcr    r1; \
 176         bt      17, 1f;         /* Exception from user mode? */ \
 177         mfsprg1 r1;             /* Kernel mode => restore orignal sp */ \
 178         b       2f; \
 179 1:      mfsprg0 r1;             /* User mode => Load kernel stack */ \
 180 2:      mtcr    r10;            /* Restore cr */ \
 181         mfsprg3 r10;            /* Restore r10 */ \
 182         SAVE_ALL ; \
 183         li      r10, id; \
 184         ABS_JUMP(xfer);
 185 
 186 #define INTR_ENTRY(offset, name, id) \
 187                 EXCEPTION_ENTRY(offset, name, id, interrupt_common)
 188 
 189 #define TRAP_ENTRY(offset, name, id) \
 190                 EXCEPTION_ENTRY(offset, name, id, trap_common)
 191 
 192 /*
 193  * Macro to build a system call entry.
 194  */
 195 #define SYSC_ENTRY(offset, name, id) \
 196         .skip offset - (. - exception_vector); \
 197 exception_##name: \
 198         mtsprg1 r1;             /* sprg1: current sp */ \
 199         mfsprg0 r1;             /* Load kernel stack */ \
 200         SAVE_ALL ; \
 201         li      r10, id; \
 202         ABS_JUMP(syscall_entry);
 203 
 204 /*
 205  * Exception vectors
 206  */
 207 .globl  exception_vector
 208 exception_vector:
 209         .long   0
 210 
 211         .skip 0x100 - (. - exception_vector); \
 212 ENTRY(system_reset)
 213         ABS_JUMP(kernel_start)
 214 
 215 TRAP_ENTRY(0x200, machine_check  ,TRAP_MACHINE_CHECK)
 216 TRAP_ENTRY(0x300, dsi            ,TRAP_DSI)
 217 TRAP_ENTRY(0x400, isi            ,TRAP_ISI)
 218 INTR_ENTRY(0x500, external_intr  ,TRAP_EXT_INTERRUPT)
 219 TRAP_ENTRY(0x600, alignment      ,TRAP_ALIGNMENT)
 220 TRAP_ENTRY(0x700, program        ,TRAP_PROGRAM)
 221 TRAP_ENTRY(0x800, fp_unavailable ,TRAP_FP_UNAVAILABLE)
 222 INTR_ENTRY(0x900, decrementer    ,TRAP_DECREMENTER)
 223 SYSC_ENTRY(0xc00, syscall        ,TRAP_SYSTEM_CALL)
 224 TRAP_ENTRY(0xd00, trace          ,TRAP_TRACE)
 225 TRAP_ENTRY(0xe00, fp_assist      ,TRAP_FP_ASSIST)
 226 
 227 .globl  exception_vector_end
 228 exception_vector_end:
 229 
 230 
 231 /*
 232  * Kernel start point
 233  */
 234 ENTRY(kernel_start)
 235         /*
 236          * Setup CPU registers.
 237          */
 238         li      r3, MSR_IP              /* Establish default MSR value */
 239         mtmsr   r3
 240 
 241         li      r3, 0                   /* Init interrupt nest count */
 242         mtspr   SPR_SPRG2, r3
 243 
 244         li      r3, 0                   /* Reset timebase */
 245         mttbl   r3
 246         mttbu   r3
 247         mttbl   r3
 248 
 249         /*
 250          * Init boot stack
 251          */
 252         lis     r1, BOOTSTKTOP@ha
 253         addi    r1, r1, BOOTSTKTOP@l
 254         subi    r1, r1, 16
 255 
 256         mtspr   SPR_SPRG0, r1           /* Keep kernel stack */
 257 
 258         /*
 259          * Clear kernel BSS
 260          */
 261         lis     r3, __bss@ha
 262         addi    r3, r3, __bss@l
 263         lis     r4, __end@ha
 264         addi    r4, r4, __end@l
 265         li      r0, 0
 266 1:
 267         stwu    r0, 4(r3)
 268         cmplw   cr0, r3, r4
 269         blt     1b
 270 
 271         /*
 272          * Call kernel main routine
 273          */
 274         b       main
 275         /* NOTREACHED */
 276 
 277 
 278 /*
 279  * Common entry for interrupts.
 280  * r3 - trap id
 281  */
 282 ENTRY(interrupt_common)
 283         stw     r10, CTX_TRAPNO(r1)
 284 
 285         mfsprg2 r28                     /* r28: current IRQ nesting level */
 286         addi    r3, r28, 1              /* Increment IRQ nesting level */
 287         mtsprg2 r3
 288 
 289         mfmsr   r29                     /* r29: current msr value */
 290         isync
 291         mr      r30, r1                 /* r30: trap frame */
 292         subi    r1, r1, STKFRAME_LEN    /* Adjust stack frame for C routine */
 293 
 294         cmpwi   cr0, r28, 0             /* Outermost interrupt? */
 295         bne     1f
 296         bl      sched_lock              /* If outermost, lock scheduler */
 297 1:
 298         mr      r3, r30
 299         bl      interrupt_handler       /* Call main interrupt handler */
 300 
 301         mtsprg2 r28                     /* Restore IRQ nesting level */
 302         cmpwi   cr0, r28, 0             /* Outermost interrupt? */
 303         bne     interrupt_ret
 304         bl      sched_unlock            /* Try to preempt */
 305 
 306         mtcr    r29                     /* Exception from user mode? */
 307         bf      17, interrupt_ret       /* Exit if it's from kernel mode */
 308 
 309         mfmsr   r27                     /* Enable IRQ */
 310         andi.   r4, r27, ~MSR_EE@l
 311         mtmsr   r4
 312         bl      exception_deliver       /* Check exception */
 313         mtmsr   r27                     /* Disable IRQ */
 314 interrupt_ret:
 315         mr      r1, r30                 /* Restore stack */
 316         RESTORE_ALL
 317         mfsprg1 r1                      /* restore original sp */
 318         rfi
 319 
 320 /*
 321  * System call entry
 322  */
 323         .global syscall_ret
 324 ENTRY(syscall_entry)
 325         stw     r10, CTX_TRAPNO(r1)
 326 
 327         mfmsr   r29                     /* r29: current msr value */
 328         mr      r30, r1                 /* r30: trap frame */
 329         subi    r1, r1, STKFRAME_LEN    /* Adjust stack frame for C routine */
 330 
 331         mfmsr   r27                     /* Enable IRQ */
 332         andi.   r27, r27, ~MSR_EE@l
 333         mtmsr   r27
 334 
 335         mr      r26, r0                 /* r26: saved syscall number */
 336         mr      r7, r0
 337         bl      syscall_handler         /* System call dispatcher */
 338 
 339         cmpwi   cr0, r26, 0             /* exception_return? */
 340         beq     1f                      /* Skip storing error if so */
 341         stw     r3, REG_R3(30)          /* Set return value */
 342 1:
 343         bl      exception_deliver       /* Check exception */
 344         mr      r1, r30                 /* Restore stack */
 345 syscall_ret:
 346         mfmsr   r27                     /* Disable IRQ */
 347         ori     r27, r27, MSR_EE@l
 348         mtmsr   r27
 349         RESTORE_ALL
 350         mfsprg1 r1                      /* Restore original sp */
 351         rfi
 352 
 353 /*
 354  * Common entry for exceptions.
 355  * r3 - trap id
 356  */
 357 ENTRY(trap_common)
 358         stw     r10, CTX_TRAPNO(r1)
 359 
 360         mfsprg2 r3                      /* increment nest counter */
 361         addi    r3, r3, 1
 362         mtsprg2 r3
 363 
 364         mr      r3, r1
 365         subi    r1, r1, STKFRAME_LEN
 366         bl      trap_handler
 367         addi    r1, r1, STKFRAME_LEN
 368 
 369         mfsprg2 r3                      /* decrement nest counter */
 370         addi    r3, r3, -1
 371         mtsprg2 r3
 372 
 373         RESTORE_ALL
 374         mfsprg1 r1                      /* restore original sp */
 375         rfi
 376 
 377 /*
 378  * Switch register context.
 379  * r3 = previous kern_regs, r4 = next kern_regs
 380  * Interrupts must be disabled by caller.
 381  *
 382  * syntax - void cpu_switch(kern_regs *prev, kern_regs *next)
 383  *
 384  * Note: GCC uses r0-r12 as scratch registers
 385  */
 386 ENTRY(cpu_switch)
 387         isync
 388         stw     r13, 0x00(r3)
 389         stw     r14, 0x04(r3)
 390         stw     r15, 0x08(r3)
 391         stw     r16, 0x0c(r3)
 392         stw     r17, 0x10(r3)
 393         stw     r18, 0x14(r3)
 394         stw     r19, 0x18(r3)
 395         stw     r20, 0x1c(r3)
 396         stw     r21, 0x20(r3)
 397         stw     r22, 0x24(r3)
 398         stw     r23, 0x28(r3)
 399         stw     r24, 0x2c(r3)
 400         stw     r25, 0x30(r3)
 401         stw     r26, 0x34(r3)
 402         stw     r27, 0x38(r3)
 403         stw     r28, 0x3c(r3)
 404         stw     r29, 0x40(r3)
 405         stw     r30, 0x44(r3)
 406         stw     r31, 0x48(r3)
 407         stw     r2,  0x4c(r3)
 408         stw     r1,  0x50(r3)
 409         mflr    r5
 410         stw     r5,  0x54(r3)
 411         mfcr    r5
 412         stw     r5,  0x58(r3)
 413         mfsprg0 r5                      /* Save kernel stack */
 414         stw     r5,  0x5c(r3)
 415 
 416         lwz     r13, 0x00(r4)
 417         lwz     r14, 0x04(r4)
 418         lwz     r15, 0x08(r4)
 419         lwz     r16, 0x0c(r4)
 420         lwz     r17, 0x10(r4)
 421         lwz     r18, 0x14(r4)
 422         lwz     r19, 0x18(r4)
 423         lwz     r20, 0x1c(r4)
 424         lwz     r21, 0x20(r4)
 425         lwz     r22, 0x24(r4)
 426         lwz     r23, 0x28(r4)
 427         lwz     r24, 0x2c(r4)
 428         lwz     r25, 0x30(r4)
 429         lwz     r26, 0x34(r4)
 430         lwz     r27, 0x38(r4)
 431         lwz     r28, 0x3c(r4)
 432         lwz     r29, 0x40(r4)
 433         lwz     r30, 0x44(r4)
 434         lwz     r31, 0x48(r4)
 435         lwz     r2,  0x4c(r4)
 436         lwz     r1,  0x50(r4)
 437         lwz     r5,  0x54(r4)
 438         mtlr    r5
 439         lwz     r5,  0x58(r4)
 440         mtcr    r5
 441         lwz     r5,  0x5c(r4)
 442         mtsprg0 r5                      /* Restore kernel stack */
 443         isync
 444         blr
 445 
 446 /*
 447  * void sploff(void);
 448  */
 449 ENTRY(sploff)
 450         mfmsr   r3
 451         andi.   r4, r3, ~MSR_EE@l
 452         mtmsr   r4
 453         blr
 454 
 455 /*
 456  * void splon(void);
 457  */
 458 ENTRY(splon)
 459         mfmsr   r3
 460         ori     r4, r3, MSR_EE@l
 461         mtmsr   r4
 462         blr
 463 

/* [<][>][^][v][top][bottom][index][help] */