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