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

Last change on this file since 605 was 587, checked in by bouyer, 11 years ago

Add back version string print

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