source: trunk/softs/tsar_boot/src/reset.S @ 650

Last change on this file since 650 was 634, checked in by bouyer, 11 years ago

Pass the preloader's function vector address in a0 to the next stage.
This way the next stage doesn't have to know the address of the preloader.

File size: 8.0 KB
Line 
1/*
2 * \file  : reset.S
3 * \date  : 01/12/2012
4 * \author: Cesar FUGUET & Manuel BOUYER & Alain Greiner
5 *
6 * This is a generic reset code for a generic multi-clusters / multi-processors
7 * TSAR architecture (up to 256 clusters / up to 4  processors per cluster).
8 *
9 * There is one XICU, one TTY, one DMA, and one memory bank per cluster.
10 *
11 * This preloader uses a stack segment allocated in cluster 0, defined
12 * by the seg_reset_stack_base and seg_reset_stack_size parameters in ldscript.
13 * - Processor 0 uses a larger stack:         64 Kbytes.
14 * - Other processors use a smaller stack:    512 bytes.
15 *     => the seg_stack_size cannot be smaller than 0x90000 bytes (576 K).
16 * Those stacks can be used by both the preloader and the boot-loader code.
17 *
18 * The replicated XICU is used to awake the sleeping processors:
19 *      xicu_paddr_base = ICU_PADDR_BASE + (cluster_xy << 32)
20 *
21 * It is intended to be used with various operating systems or nano kernels,
22 * including NetBSD, ALMOS, and GIET_VM.
23 *
24 * - Each processor initializes its Status Register (SR) to disable interrupts.
25 * - Each processor initializes its Count Register.
26 * - Each processor initialises its private XICU WTI mask register.
27 * - Each processor initializes its Stack Pointer.
28 * - Only processor 0 executes the reset_load_elf function to load into memory
29 *   the system specific boot-loader stored on disk at BOOT_LOADER_LBA
30 * - All other processors wait in a low power consumption mode that the
31 *   processor 0 wakes them using an IPI (Inter Processor Interruption)
32 */
33
34    #include <defs.h>
35    #include <mips32_registers.h>
36
37    /* These define should be consistent with values defined in map.xml file  */
38
39    .extern seg_reset_stack_base 
40    .extern seg_reset_stack_size   
41
42    .section .reset,"ax",@progbits
43
44    .extern dtb_addr
45    .extern reset_putc
46    .extern reset_getc
47    .extern reset_ioc_read
48    .extern reset_elf_loader
49    .extern memcpy
50    .extern reset_puts
51    .extern reset_putx
52    .extern reset_putd
53    .extern reset_ioc_init
54    .extern versionstr
55
56    .globl  reset                    /* Makes reset an external symbol */
57    .ent    reset
58
59    .align  2
60    .set noreorder
61
62reset:
63    b       _reset                  /* 0xbfc0000 */
64    nop                             /* 0xbfc0004 */
65
66    /*  Addresses of the functions provided by this reset code */
67
68preloader_vector:
69    .word   RESET_VERSION           /* 0xbfc0008 */
70    .word   dtb_addr                /* 0xbfc000c */
71    .word   reset_putc              /* 0xbfc0010 */
72    .word   reset_getc              /* 0xbfc0014 */
73    .word   reset_ioc_read          /* 0xbfc0018 */
74    .word   reset_elf_loader        /* 0xbfc001C */
75    .word   memcpy                  /* 0xbfc0020 */
76    .word   reset_puts              /* 0xbfc0024 */
77    .word   reset_putx              /* 0xbfc0028 */
78    .word   reset_putd              /* 0xbfc002C */
79
80_reset:
81
82    /* All processors Disable interruptions, keep STATUSbev enabled */
83
84    li      k0,     (1 << 22)
85    mtc0    k0,     CP0_STATUS
86
87    /* All processors compute proc_id, lpid, cluster_xy */
88
89    mfc0    k0,     CP0_EBASE
90    andi    t0,     k0,     0x3FF   /* t0 <= proc_id (at most 1024 processors)    */
91
92    move    t3,     t0
93
94    la      k0,     NB_PROCS        /* k0 <= number of processors per cluster     */
95    divu    t3,     k0
96    mfhi    t1                      /* t1 <= lpid       = proc_id % NB_PROCS      */
97    mflo    t2                      /* t2 <= cluster_xy = proc_id / NB_PROCS      */
98
99    /* All processors initialise the count register in CP0 */
100
101    mtc0    zero,   CP0_COUNT
102
103    /*
104     * All processors enable the WTI for XICU
105     * Each processor may have IRQ_PER_PROC irq outputs from the XICU
106     * In each cluster, the XICU base address depends on the cluster_xy
107     */
108
109    la      t3,     ICU_PADDR_BASE  /* t3 <= ICU base address                     */
110    move    t4,     t1              /* t4 <= local_id                             */
111    li      t5,     IRQ_PER_PROC    /* t5 <= IRQ_PER_PROC                         */
112    multu   t4,     t5             
113    mflo    t6                      /* t6 <= IRQ_PER_PROC * local_id              */
114    sll     t4,     t6,     2       /* t4 <= OUT_INDEX = t6 * 4                   */
115
116    li      t5,     (0xC << 7)      /* t5 <= FUNC      = XICU_MSK_WTI             */
117    or      t4,     t4,     t5      /* t4 <= FUNC | INDEX | 00                    */
118    or      t5,     t3,     t4      /* t5 <= &XICU[MSK_WTI][OUT_INDEX]            */
119   
120    /* All processors set WTI mask using the physical address extension    */
121
122    li      t4,     1
123    sllv    t4,     t4,     t1      /* Set XICU[MSK_WTI][INDEX][local_id]         */
124
125    mtc2    t2,     CP2_PADDR_EXT   /* set PADDR extension                        */
126    sw      t4,     0(t5)           /* XICU[MSK_WTI][INDEX] <= t4                 */
127    mtc2    zero,   CP2_PADDR_EXT   /* reset PADDR extension                      */
128
129    /* All processors initializes stack pointer, depending on proc_id */
130
131   la      k0,      seg_reset_stack_base
132   li      k1,      0x10000         /* k1 <= P0 stack size == 64 Kbytes           */
133   addu    sp,      k0,     k1      /* P0 stack from base to (base + 64K)         */
134
135   li      k1,      0x200           /* k1 <= Pi stack size == 512 bytes           */
136   multu   k1,      t0             
137   mflo    k0                       /* k0 <= 256 * proc_id                        */
138   addu    sp,      sp,     k1
139   addu    sp,      sp,     k0      /* Pi stacks from base + 64K + proc_id*256    */
140
141    /*
142     * Only processor 0 in cluster 0 loads and executes the boot-loader
143     * We have:
144     * t0: global proc_id
145     * t1: local proc_id
146     * t2: cluster_xy
147     * t3: xicu physical base address in cluster 0
148     */
149
150    bne     zero,   t0,     _reset_wait
151    nop
152
153    /* Processor 0 displays version for this reset code */
154
155    la      a0,     versionstr
156    la      k0,     reset_puts
157    jalr    k0
158    nop
159
160
161#ifndef SOCLIB_IOC
162
163    /* Processor 0 Initialize the block device if required */
164
165    la      k0,     reset_ioc_init
166    jalr    k0
167    nop
168
169#endif
170
171    /*
172     * Processor 0 jumps to the reset_elf_loader routine
173     * Passing as argument the block number in which is loaded the .elf file
174     */
175
176    la      k0,     reset_elf_loader
177    li      a0,     BOOT_LOADER_LBA
178    jalr    k0
179    nop
180
181    /*
182     * Processor O jumps to the entry address defined in the .elf file,
183     * and returned by reset_elf_loader function.
184     * First argument is pointer to the preloader function vectors
185     * other function arguments are 0
186     */
187
188    la      a0,     preloader_vector
189    move    a1,     zero
190    move    a2,     zero
191    move    a3,     zero
192    jr      v0
193    nop
194
195    /*
196     * All processor (but processor 0) wait in low power mode
197     * until processor 0 wakes them using an IPI.
198     * We have:
199     * t0: global id
200     * t1: local id
201     * t2: cluster id
202     * t3: xicu physical base address in cluster 0
203     */
204
205_reset_wait:
206
207    sll     t4,     t1,     2       /* t4 <= local_id * 4                 */
208    addu    t5,     t4,     t3      /* t5 <= &XICU[WTI_REG][local_id]     */
209
210    wait
211
212    /*
213     * All other processors, when exiting wait mode,
214     * read from XICU the address to jump.
215     * This address is the boot-loader entry address that has been
216     * written in the mailbox by the IPI sent by processor 0
217     */
218
219    mtc2    t2,     CP2_PADDR_EXT   /* set PADDR extension                */
220    lw      k0,     0(t5)           /* k0 <= XICU[WTI_REG][local_id]      */
221    mtc2    zero,   CP2_PADDR_EXT   /* reset PADDR extension              */
222
223    jr      k0
224    nop
225
226/* Exception entry point */
227
228.org 0x0380
229_excep:
230    mfc0    a0, CP0_STATUS          /* first arg is status                */
231    mfc0    a1, CP0_CAUSE           /* second arg is cause                */
232    mfc0    a2, CP0_EPC             /* third argc is epc                  */
233    nop
234    j       handle_except
235    nop
236
237    .end reset
238
239    .set reorder
240
241/*
242 * vim: tabstop=4 : shiftwidth=4 : expandtab
243 */
Note: See TracBrowser for help on using the repository browser.