linux/arch/nios2/kernel/head.S
<<
>>
Prefs
   1/*
   2 * Copyright (C) 2009 Wind River Systems Inc
   3 *   Implemented by fredrik.markstrom@gmail.com and ivarholmqvist@gmail.com
   4 * Copyright (C) 2004 Microtronix Datacom Ltd
   5 * Copyright (C) 2001 Vic Phillips, Microtronix Datacom Ltd.
   6 *
   7 * Based on head.S for Altera's Excalibur development board with nios processor
   8 *
   9 * Based on the following from the Excalibur sdk distribution:
  10 *      NA_MemoryMap.s, NR_JumpToStart.s, NR_Setup.s, NR_CWPManager.s
  11 *
  12 * This file is subject to the terms and conditions of the GNU General Public
  13 * License. See the file "COPYING" in the main directory of this archive
  14 * for more details.
  15 */
  16
  17#include <linux/init.h>
  18#include <linux/linkage.h>
  19#include <asm/thread_info.h>
  20#include <asm/processor.h>
  21#include <asm/cache.h>
  22#include <asm/page.h>
  23#include <asm/asm-offsets.h>
  24#include <asm/asm-macros.h>
  25
  26/*
  27 * ZERO_PAGE is a special page that is used for zero-initialized
  28 * data and COW.
  29 */
  30.data
  31.global empty_zero_page
  32.align 12
  33empty_zero_page:
  34        .space  PAGE_SIZE
  35
  36/*
  37 * This global variable is used as an extension to the nios'
  38 * STATUS register to emulate a user/supervisor mode.
  39 */
  40        .data
  41        .align  2
  42        .set noat
  43
  44        .global _current_thread
  45_current_thread:
  46        .long   0
  47/*
  48 * Input(s): passed from u-boot
  49 *   r4 - Optional pointer to a board information structure.
  50 *   r5 - Optional pointer to the physical starting address of the init RAM
  51 *        disk.
  52 *   r6 - Optional pointer to the physical ending address of the init RAM
  53 *        disk.
  54 *   r7 - Optional pointer to the physical starting address of any kernel
  55 *        command-line parameters.
  56 */
  57
  58/*
  59 * First executable code - detected and jumped to by the ROM bootstrap
  60 * if the code resides in flash (looks for "Nios" at offset 0x0c from
  61 * the potential executable image).
  62 */
  63        __HEAD
  64ENTRY(_start)
  65        wrctl   status, r0              /* Disable interrupts */
  66
  67        /* Initialize all cache lines within the instruction cache */
  68        movia   r1, NIOS2_ICACHE_SIZE
  69        movui   r2, NIOS2_ICACHE_LINE_SIZE
  70
  71icache_init:
  72        initi   r1
  73        sub     r1, r1, r2
  74        bgt     r1, r0, icache_init
  75        br      1f
  76
  77        /*
  78         * This is the default location for the exception handler. Code in jump
  79         * to our handler
  80         */
  81ENTRY(exception_handler_hook)
  82        movia   r24, inthandler
  83        jmp     r24
  84
  85ENTRY(fast_handler)
  86        nextpc et
  87helper:
  88        stw     r3, r3save - helper(et)
  89
  90        rdctl   r3 , pteaddr
  91        srli    r3, r3, 12
  92        slli    r3, r3, 2
  93        movia   et, pgd_current
  94
  95        ldw     et, 0(et)
  96        add     r3, et, r3
  97        ldw     et, 0(r3)
  98
  99        rdctl   r3, pteaddr
 100        andi    r3, r3, 0xfff
 101        add     et, r3, et
 102        ldw     et, 0(et)
 103        wrctl   tlbacc, et
 104        nextpc  et
 105helper2:
 106        ldw     r3, r3save - helper2(et)
 107        subi    ea, ea, 4
 108        eret
 109r3save:
 110        .word 0x0
 111ENTRY(fast_handler_end)
 112
 1131:
 114        /*
 115         * After the instruction cache is initialized, the data cache must
 116         * also be initialized.
 117         */
 118        movia   r1, NIOS2_DCACHE_SIZE
 119        movui   r2, NIOS2_DCACHE_LINE_SIZE
 120
 121dcache_init:
 122        initd   0(r1)
 123        sub     r1, r1, r2
 124        bgt     r1, r0, dcache_init
 125
 126        nextpc  r1                      /* Find out where we are */
 127chkadr:
 128        movia   r2, chkadr
 129        beq     r1, r2,finish_move      /* We are running in RAM done */
 130        addi    r1, r1,(_start - chkadr)        /* Source */
 131        movia   r2, _start              /* Destination */
 132        movia   r3, __bss_start         /* End of copy */
 133
 134loop_move:                              /* r1: src, r2: dest, r3: last dest */
 135        ldw     r8, 0(r1)               /* load a word from [r1] */
 136        stw     r8, 0(r2)               /* store a word to dest [r2] */
 137        flushd  0(r2)                   /* Flush cache for safety */
 138        addi    r1, r1, 4               /* inc the src addr */
 139        addi    r2, r2, 4               /* inc the dest addr */
 140        blt     r2, r3, loop_move
 141
 142        movia   r1, finish_move         /* VMA(_start)->l1 */
 143        jmp     r1                      /* jmp to _start */
 144
 145finish_move:
 146
 147        /* Mask off all possible interrupts */
 148        wrctl   ienable, r0
 149
 150        /* Clear .bss */
 151        movia   r2, __bss_start
 152        movia   r1, __bss_stop
 1531:
 154        stb     r0, 0(r2)
 155        addi    r2, r2, 1
 156        bne     r1, r2, 1b
 157
 158        movia   r1, init_thread_union   /* set stack at top of the task union */
 159        addi    sp, r1, THREAD_SIZE
 160        movia   r2, _current_thread     /* Remember current thread */
 161        stw     r1, 0(r2)
 162
 163        movia   r1, nios2_boot_init     /* save args r4-r7 passed from u-boot */
 164        callr   r1
 165
 166        movia   r1, start_kernel        /* call start_kernel as a subroutine */
 167        callr   r1
 168
 169        /* If we return from start_kernel, break to the oci debugger and
 170         * buggered we are.
 171         */
 172        break
 173
 174        /* End of startup code */
 175.set at
 176