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

Last change on this file since 646 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
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:
[606]19 *      xicu_paddr_base = ICU_PADDR_BASE + (cluster_xy << 32)
[586]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
[606]37    /* These define should be consistent with values defined in map.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
[634]68preloader_vector:
[586]69    .word   RESET_VERSION           /* 0xbfc0008 */
[292]70    .word   dtb_addr                /* 0xbfc000c */
[586]71    .word   reset_putc              /* 0xbfc0010 */
72    .word   reset_getc              /* 0xbfc0014 */
73    .word   reset_ioc_read          /* 0xbfc0018 */
74    .word   reset_elf_loader        /* 0xbfc001C */
[425]75    .word   memcpy                  /* 0xbfc0020 */
[586]76    .word   reset_puts              /* 0xbfc0024 */
77    .word   reset_putx              /* 0xbfc0028 */
78    .word   reset_putd              /* 0xbfc002C */
[292]79
[586]80_reset:
[292]81
[586]82    /* All processors Disable interruptions, keep STATUSbev enabled */
83
[292]84    li      k0,     (1 << 22)
85    mtc0    k0,     CP0_STATUS
86
[606]87    /* All processors compute proc_id, lpid, cluster_xy */
[292]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
[606]96    mfhi    t1                      /* t1 <= lpid       = proc_id % NB_PROCS      */
97    mflo    t2                      /* t2 <= cluster_xy = proc_id / NB_PROCS      */
[292]98
[586]99    /* All processors initialise the count register in CP0 */
[292]100
101    mtc0    zero,   CP0_COUNT
102
[586]103    /*
104     * All processors enable the WTI for XICU
105     * Each processor may have IRQ_PER_PROC irq outputs from the XICU
[606]106     * In each cluster, the XICU base address depends on the cluster_xy
[292]107     */
[302]108
[586]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                         */
[302]112    multu   t4,     t5             
[586]113    mflo    t6                      /* t6 <= IRQ_PER_PROC * local_id              */
114    sll     t4,     t6,     2       /* t4 <= OUT_INDEX = t6 * 4                   */
[302]115
[586]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]            */
[292]119   
[586]120    /* All processors set WTI mask using the physical address extension    */
[292]121
122    li      t4,     1
[586]123    sllv    t4,     t4,     t1      /* Set XICU[MSK_WTI][INDEX][local_id]         */
[292]124
[606]125    mtc2    t2,     CP2_PADDR_EXT   /* set PADDR extension                        */
[586]126    sw      t4,     0(t5)           /* XICU[MSK_WTI][INDEX] <= t4                 */
127    mtc2    zero,   CP2_PADDR_EXT   /* reset PADDR extension                      */
[567]128
[586]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
[292]143     * We have:
[586]144     * t0: global proc_id
145     * t1: local proc_id
[606]146     * t2: cluster_xy
[586]147     * t3: xicu physical base address in cluster 0
[292]148     */
149
150    bne     zero,   t0,     _reset_wait
151    nop
152
[586]153    /* Processor 0 displays version for this reset code */
[292]154
[587]155    la      a0,     versionstr
156    la      k0,     reset_puts
157    jalr    k0
158    nop
[292]159
[502]160
[292]161#ifndef SOCLIB_IOC
162
[586]163    /* Processor 0 Initialize the block device if required */
[292]164
[586]165    la      k0,     reset_ioc_init
[292]166    jalr    k0
167    nop
168
169#endif
170
[586]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
[292]174     */
175
[586]176    la      k0,     reset_elf_loader
[292]177    li      a0,     BOOT_LOADER_LBA
178    jalr    k0
179    nop
180
[586]181    /*
182     * Processor O jumps to the entry address defined in the .elf file,
183     * and returned by reset_elf_loader function.
[634]184     * First argument is pointer to the preloader function vectors
185     * other function arguments are 0
[292]186     */
187
[634]188    la      a0,     preloader_vector
[292]189    move    a1,     zero
190    move    a2,     zero
191    move    a3,     zero
192    jr      v0
193    nop
194
[586]195    /*
196     * All processor (but processor 0) wait in low power mode
197     * until processor 0 wakes them using an IPI.
[292]198     * We have:
199     * t0: global id
200     * t1: local id
201     * t2: cluster id
[586]202     * t3: xicu physical base address in cluster 0
[292]203     */
204
[586]205_reset_wait:
[292]206
[586]207    sll     t4,     t1,     2       /* t4 <= local_id * 4                 */
208    addu    t5,     t4,     t3      /* t5 <= &XICU[WTI_REG][local_id]     */
209
[292]210    wait
211
[586]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     */
[567]218
[606]219    mtc2    t2,     CP2_PADDR_EXT   /* set PADDR extension                */
[567]220    lw      k0,     0(t5)           /* k0 <= XICU[WTI_REG][local_id]      */
221    mtc2    zero,   CP2_PADDR_EXT   /* reset PADDR extension              */
222
[292]223    jr      k0
224    nop
225
226/* Exception entry point */
[586]227
[292]228.org 0x0380
229_excep:
[586]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                  */
[292]233    nop
234    j       handle_except
235    nop
236
[586]237    .end reset
[292]238
239    .set reorder
[302]240
241/*
242 * vim: tabstop=4 : shiftwidth=4 : expandtab
243 */
Note: See TracBrowser for help on using the repository browser.