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

Last change on this file since 1055 was 1049, checked in by alain, 8 years ago

Cosmetic change in the hard_config.h file : XCU -> ICU , TTY -> TXT

File size: 9.7 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
[755]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 *
[755]11 * This preloader uses a stack segment allocated in cluster 0 for processor 0.
12 * The stack allocation is not performed for other processors as they do not
13 * need it during the preloader execution. Therefore, this allocation should be
14 * done by the loaded Operating System.
15 *
[586]16 * The replicated XICU is used to awake the sleeping processors:
[606]17 *      xicu_paddr_base = ICU_PADDR_BASE + (cluster_xy << 32)
[586]18 *
19 * It is intended to be used with various operating systems or nano kernels,
[755]20 * including NetBSD, Linux, ALMOS, and GIET_VM.
[586]21 *
22 * - Each processor initializes its Status Register (SR) to disable interrupts.
23 * - Each processor initializes its Count Register.
24 * - Each processor initialises its private XICU WTI mask register.
[755]25 * - Only processor 0 executes the reset_load_elf function to load into memory
[758]26 *   the system specific boot-loader stored on disk at RESET_LOADER_LBA
[586]27 * - All other processors wait in a low power consumption mode that the
28 *   processor 0 wakes them using an IPI (Inter Processor Interruption)
[292]29 */
30
31    #include <defs.h>
32    #include <mips32_registers.h>
33
[606]34    /* These define should be consistent with values defined in map.xml file  */
[292]35
[586]36    .section .reset,"ax",@progbits
37
38    .extern reset_putc
39    .extern reset_getc
40    .extern reset_ioc_read
41    .extern reset_elf_loader
[425]42    .extern memcpy
[586]43    .extern reset_puts
44    .extern reset_putx
45    .extern reset_putd
46    .extern reset_ioc_init
[502]47    .extern versionstr
[949]48    .extern dtb_start
49    .extern dtb_addr
[292]50
[586]51    .globl  reset                    /* Makes reset an external symbol */
52    .ent    reset
[292]53
54    .align  2
55    .set noreorder
56
[586]57reset:
[755]58    b       _reset                   /* 0xbfc0000 */
59    nop                              /* 0xbfc0004 */
[292]60
[586]61    /*  Addresses of the functions provided by this reset code */
[292]62
[634]63preloader_vector:
[755]64    .word   RESET_VERSION            /* 0xbfc0008 */
[949]65    .word   dtb_start                /* 0xbfc000c */
[755]66    .word   reset_putc               /* 0xbfc0010 */
67    .word   reset_getc               /* 0xbfc0014 */
68    .word   reset_ioc_read           /* 0xbfc0018 */
69    .word   reset_elf_loader         /* 0xbfc001C */
70    .word   memcpy                   /* 0xbfc0020 */
71    .word   reset_puts               /* 0xbfc0024 */
72    .word   reset_putx               /* 0xbfc0028 */
73    .word   reset_putd               /* 0xbfc002C */
[292]74
[586]75_reset:
[292]76
[586]77    /* All processors Disable interruptions, keep STATUSbev enabled */
78
[292]79    li      k0,     (1 << 22)
80    mtc0    k0,     CP0_STATUS
81
[801]82    /*
83     * All processors compute gpid, lpid, cluster_xy
[833]84     * gpid = ebase[11:0] = X_WIDTH : Y_WIDTH : P_WIDTH
[801]85     *                        x         y       lpid
86     * X, Y and LPID fields are left-aligned
87     */
[292]88
89    mfc0    k0,     CP0_EBASE
[833]90    andi    t0,     k0,     0xFFF            /* t0 <= gpid (<= 4096 procs)  */
[801]91    andi    t1,     t0,     ((1<<P_WIDTH)-1) /* t1 <= lpid                  */
92    srl     t2,     t0,     P_WIDTH          /* t2 <= cluster_xy            */
[292]93
[1042]94    /* All processors initialize the count register in CP0 */
[292]95
96    mtc0    zero,   CP0_COUNT
97
[1042]98#if USE_32BIT
[1049]99
[1042]100    /*** VERSION 1 : 32 bits ***/
101
[586]102    /*
[1042]103     * If the addresses are 32-bit wide, we need to compute the address
104     * if the XICU for each cluster
[755]105     * All processors enable the WTI for XICU
[586]106     * Each processor may have IRQ_PER_PROC irq outputs from the XICU
[755]107     * In each cluster, the XICU base address depends on the cluster_xy
[292]108     */
[1049]109    la      t3,     SEG_ICU_BASE      /* t3 <= ICU base address             */
[1042]110    li      t4,     1                 /* t4 <= 1                            */
111    sll     t4,     t4,     X_WIDTH   /* t4 <= 1 << X_WIDTH                 */
112    li      t5,     1                 /* t5 <= 1                            */
113    sll     t5,     t5,     Y_WIDTH   /* t5 <= 1 << Y_WIDTH                 */
114    multu   t4,     t5                /* X_WIDTH * Y_WIDTH                  */
115    mflo    t4                        /* t4 <= X_WIDTH * Y_WIDTH            */
116    lui     t5,     0x8000            /* t5 <= 0x80000000                   */
117    divu    t5,     t4                /* (Address increment per cluster) / 2*/
118    mflo    t4                        /* t4 <= Increment / 2                */
119    sll     t4,     t4,     1         /* t4 <= Address increment per clus.  */
120    mult    t4,     t2                /* Cluster increment * Cluster num.   */
121    mflo    t4                        /* Cluster base address               */
122    addu    t3,     t3,     t4        /* t3 <= XICU base address in clus.   */
[302]123
[1042]124    move    t4,     t1                /* t4 <= local_id                     */
125    li      t5,     IRQ_PER_PROCESSOR /* t5 <= IRQ_PER_PROCESSOR            */
126    multu   t4,     t5
127    mflo    t6                       /* t6 <= IRQ_PER_PROC * local_id       */
128    sll     t4,     t6,     2        /* t4 <= OUT_INDEX = t6 * 4            */
129
130    li      t5,     (0xC << 7)       /* t5 <= FUNC      = XICU_MSK_WTI      */
131    or      t4,     t4,     t5       /* t4 <= FUNC | INDEX | 00             */
132    or      t5,     t3,     t4       /* t5 <= &XICU[MSK_WTI][OUT_INDEX]     */
133
134    /* All processors set WTI mask */
135
136    li      t4,     1
137    sllv    t4,     t4,     t1       /* Set XICU[MSK_WTI][INDEX][local_id]  */
138    sw      t4,     0(t5)            /* XICU[MSK_WTI][INDEX] <= t4          */
[1049]139
[1042]140#else
[1049]141
[1042]142    /*** VERSION 2 : 40 bits ***/
143
144    /*
145     * All processors enable the WTI for XICU
146     * Each processor may have IRQ_PER_PROC irq outputs from the XICU
147     * In each cluster, the XICU base address depends on the cluster_xy
148     */
[1049]149    la      t3,     SEG_ICU_BASE      /* t3 <= ICU base address             */
[758]150    move    t4,     t1                /* t4 <= local_id                     */
151    li      t5,     IRQ_PER_PROCESSOR /* t5 <= IRQ_PER_PROCESSOR            */
[755]152    multu   t4,     t5
153    mflo    t6                       /* t6 <= IRQ_PER_PROC * local_id       */
154    sll     t4,     t6,     2        /* t4 <= OUT_INDEX = t6 * 4            */
[302]155
[755]156    li      t5,     (0xC << 7)       /* t5 <= FUNC      = XICU_MSK_WTI      */
157    or      t4,     t4,     t5       /* t4 <= FUNC | INDEX | 00             */
158    or      t5,     t3,     t4       /* t5 <= &XICU[MSK_WTI][OUT_INDEX]     */
[292]159
[755]160    /* All processors set WTI mask using the physical address extension */
161
[292]162    li      t4,     1
[755]163    sllv    t4,     t4,     t1       /* Set XICU[MSK_WTI][INDEX][local_id]  */
[292]164
[755]165    mtc2    t2,     CP2_PADDR_EXT    /* set PADDR extension                 */
166    sw      t4,     0(t5)            /* XICU[MSK_WTI][INDEX] <= t4          */
167    mtc2    zero,   CP2_PADDR_EXT    /* reset PADDR extension               */
[1049]168
[1042]169#endif
[567]170
[586]171    /*
[1042]172     * Only the bootstrap processor loads and executes the boot-loader
[292]173     * We have:
[755]174     * t0: global pid
175     * t1: local pid
[606]176     * t2: cluster_xy
[1042]177     * t3: xicu physical base address in bootstrap cluster
[292]178     */
179
[1042]180    li      t4,     BS_PROC
181    bne     t4,     t0,     _reset_wait
[292]182    nop
183
[1042]184    /* Bootstrap Processor initializes stack pointer */
[755]185
186    la      k0,     _stack
187    li      k1,     RESET_STACK_SIZE /* k1 <= P0 stack size                 */
188    addu    sp,     k0,     k1       /* P0 stack from base to (base + size) */
189
[1042]190    /* Bootstrap Processor displays version for this reset code */
[292]191
[587]192    la      a0,     versionstr
[758]193    jal     reset_puts
[587]194    nop
[292]195
[1042]196    /* Bootstrap Processor initializes the block device */
[502]197
[758]198    jal     reset_ioc_init
[292]199    nop
200
[586]201    /*
[1042]202     * Bootstrap Processor jumps to the reset_elf_loader routine passing as argument
[755]203     * the block number in which is loaded the .elf file
[292]204     */
205
[758]206    li      a0,     RESET_LOADER_LBA
207    jal     reset_elf_loader
[292]208    nop
209
[755]210    /*
[1042]211     * Bootstrap Processor jumps to the entry address defined in the .elf file, and
[755]212     * returned by reset_elf_loader function.
213     * First argument is pointer to the preloader function vectors other
214     * function arguments are 0
[292]215     */
216
[755]217    la      a0,     preloader_vector
[949]218    lw      a1,     dtb_addr
[292]219    move    a2,     zero
220    move    a3,     zero
221    jr      v0
222    nop
223
[586]224    /*
[755]225     * All processor (but processor 0) wait in low power mode until processor 0
226     * wakes them using an IPI.
[292]227     * We have:
228     * t0: global id
229     * t1: local id
230     * t2: cluster id
[586]231     * t3: xicu physical base address in cluster 0
[292]232     */
233
[586]234_reset_wait:
[292]235
[755]236    sll     t4,     t1,     2        /* t4 <= local_id * 4                  */
237    addu    t5,     t4,     t3       /* t5 <= &XICU[WTI_REG][local_id]      */
[586]238
[292]239    wait
240
[755]241    /*
242     * All other processors, when exiting wait mode, read from XICU the address
243     * to jump.
244     * This address is the boot-loader entry address that has been written in
245     * the mailbox by the IPI sent by processor 0
[586]246     */
[567]247
[755]248    mtc2    t2,     CP2_PADDR_EXT    /* set PADDR extension                 */
249    lw      k0,     0(t5)            /* k0 <= XICU[WTI_REG][local_id]       */
250    mtc2    zero,   CP2_PADDR_EXT    /* reset PADDR extension               */
[567]251
[292]252    jr      k0
253    nop
254
255/* Exception entry point */
[586]256
[292]257.org 0x0380
258_excep:
[755]259    mfc0    a0,     CP0_STATUS       /* first arg is status                 */
260    mfc0    a1,     CP0_CAUSE        /* second arg is cause                 */
261    mfc0    a2,     CP0_EPC          /* third argc is epc                   */
262    mfc2    a3,     CP2_DBVAR        /* fourth argc is dbvar                */
[292]263    nop
264    j       handle_except
265    nop
266
[586]267    .end reset
[292]268
269    .set reorder
[302]270
[755]271    .section .data
272
273_stack:
274
275    .space RESET_STACK_SIZE
276
[302]277/*
278 * vim: tabstop=4 : shiftwidth=4 : expandtab
279 */
Note: See TracBrowser for help on using the repository browser.