source: trunk/boot/tsar_mips32/boot.c @ 557

Last change on this file since 557 was 557, checked in by nicolas.van.phan@…, 3 years ago

Add cluster_info[][] array in cluster descriptor

File size: 40.3 KB
Line 
1/*
2 * boot.c - TSAR bootloader implementation.
3 *
4 * Authors :   Alain Greiner / Vu Son  (2016)
5 *
6 * Copyright (c) UPMC Sorbonne Universites
7 *
8 * This file is part of ALMOS-MKH.
9 *
10 * ALMOS-MKH is free software; you can redistribute it and/or modify it
11 * under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; version 2.0 of the License.
13 *
14 * ALMOS-MKH is distributed in the hope that it will be useful, but
15 * WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17 * General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with ALMOS-MKH; if not, write to the Free Software Foundation,
21 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
22 */
23
24/****************************************************************************
25 * This file contains the ALMOS-MKH. boot-loader for the TSAR architecture. *
26 *                                                                          *
27 * It supports clusterised shared memory multi-processor architectures,     *
28 * where each processor core is identified by a composite index [cxy,lid]   *
29 * with one physical memory bank per cluster.                               *
30 *                                                                          *
31 * The 'boot.elf' file (containing the boot-loader binary code) is stored   *
32 * on disk and is loaded into memory by core[0,0] (cxy = 0 / lid = 0),      *
33 * and is copied in each other cluter by the local CP0 (lid = 0].           *
34 *                                                                          *
35 * 1) The boot-loader first phase is executed by core[0,0], while           *
36 *    all other cores are waiting in the preloader.                         *
37 *    It does the following tasks:                                          *
38 *      - load into the memory bank of cluster 0 the 'arch_info.bin'        *
39 *        file (containing the hardware architecture description) and the   *
40 *        'kernel.elf' file, at temporary locations,                        *   
41 *      - initializes the 'boot_info_t' structure in cluster(0,0)           *
42 *        (there is 1 'boot_info_t' per cluster), which contains both       *
43 *        global and cluster specific information that will be used for     *
44 *        kernel initialisation.                                            *
45 *      - activate CP0s in all other clusters, using IPIs.                  *
46 *      - wait completion reports from CP0s on a global barrier.            *
47 *                                                                          *
48 * 2) The boot-loader second phase is then executed in parallel by all      *
49 *    CP0s (other than core[0,0]). Each CP0 performs the following tasks:   *
50 *      - copies into the memory bank of the local cluster the 'boot.elf',  *
51 *        the 'arch_info.bin' (at the same addresses as the 'boot.elf' and  *
52 *        the 'arch_info.bin' in the memory bank of the cluster(0,0), and   *
53 *        the kernel image (at address 0x0),                                *
54 *      - initializes the 'boot_info_t' structure of the local cluster,     *
55 *      - activate all other cores in the same cluster (CPi).               *
56 *      - wait local CPi completion reports on a local barrier.             *
57 *      - report completion to bscpu on the global barrier.                 *
58 *                                                                          *
59 * 3) The boot-loader third phase is executed in parallel by all cores.     *
60 *    After passing the global barrier the bscpu:                           *
61 *      - activates the CPi of cluster(0),                                  *
62 *      - blocks on the local barrier waiting for all local CPi to report   *
63 *        completion on the local barrier,                                  *
64 *      - moves the local kernel image from the temporary location to the   *
65 *        address 0x0, (erasing the preloader code).                        *
66 *                                                                          *
67 * 4) All cores have finished the boot phase, they jump to the kern_init()  *
68 *    function (maybe not at the same time).                                *
69 ****************************************************************************/
70
71#include <elf-types.h>
72#include <hal_kernel_types.h>
73
74#include <kernel_config.h>
75#include <boot_config.h>
76
77#include <arch_info.h>
78#include <boot_info.h>
79
80#include <cluster_info.h>
81
82#include <boot_utils.h>
83#include <boot_fat32.h>
84#include <boot_bdv_driver.h>
85#include <boot_hba_driver.h>
86#include <boot_spi_driver.h>
87#include <boot_tty_driver.h>
88
89/*****************************************************************************
90 *                                 Macros.                             
91 ****************************************************************************/
92
93#define PAGE_ROUND_DOWN(x)  ((x) & (~PPM_PAGE_SIZE -1))
94#define PAGE_ROUND_UP(x)    (((x) + PPM_PAGE_SIZE-1) &   \
95                            (~(PPM_PAGE_SIZE-1)))
96
97/*****************************************************************************
98 *                             Global variables.                           
99 ****************************************************************************/
100
101// synchronization variables.
102
103volatile boot_remote_spinlock_t tty0_lock;       // protect TTY0 access
104volatile boot_remote_barrier_t  global_barrier;  // synchronize CP0 cores
105volatile boot_remote_barrier_t  local_barrier;   // synchronize cores in one cluster
106uint32_t                        active_cp0s_nr;  // number of expected CP0s
107 
108// kernel segments layout variables
109
110uint32_t                        seg_kcode_base;   // kcode segment base address
111uint32_t                        seg_kcode_size;   // kcode segment size (bytes)
112uint32_t                        seg_kdata_base;   // kdata segment base address
113uint32_t                        seg_kdata_size;   // kdata segment size (bytes)
114uint32_t                        seg_kentry_base;  // kcode segment base address
115uint32_t                        seg_kentry_size;  // kcode segment size (bytes)
116
117uint32_t                        kernel_entry;    // kernel entry point
118
119// address used by the WTI to activate remote CP0s
120
121// Functions called by boot_entry.S must be externs.
122extern void boot_entry( void );    // boot_loader entry point
123extern void boot_loader( lid_t lid, cxy_t cxy );
124
125/*********************************************************************************
126 * This function returns the printable string for each device type
127 ********************************************************************************/
128static const char * device_type_str( boot_device_types_t dev_type ) {
129    switch (dev_type) {
130        case DEV_TYPE_RAM_SCL: return "RAM_SCL";
131        case DEV_TYPE_ROM_SCL: return "ROM_SCL";
132        case DEV_TYPE_FBF_SCL: return "FBF_SCL";
133        case DEV_TYPE_IOB_TSR: return "IOB_TSR";
134        case DEV_TYPE_IOC_BDV: return "IOC_BDV";
135        case DEV_TYPE_IOC_HBA: return "IOC_HBA";
136        case DEV_TYPE_IOC_SDC: return "IOC_SDC";
137        case DEV_TYPE_IOC_SPI: return "IOC_SPI";
138        case DEV_TYPE_IOC_RDK: return "IOC_RDK";
139        case DEV_TYPE_MMC_TSR: return "MMC_TSR";
140        case DEV_TYPE_DMA_SCL: return "DMA_SCL";
141        case DEV_TYPE_NIC_CBF: return "NIC_CBF";
142        case DEV_TYPE_TIM_SCL: return "TIM_SCL";
143        case DEV_TYPE_TXT_TTY: return "TXT_TTY";
144        case DEV_TYPE_TXT_MTY: return "TXT_MTY";
145        case DEV_TYPE_ICU_XCU: return "ICU_XCU";
146        case DEV_TYPE_PIC_TSR: return "PIC_TSR";
147        default:               return "undefined";
148    }
149}
150
151/************************************************************************************
152 * This function loads the arch_info.bin file into the boot cluster memory.
153 ***********************************************************************************/
154static void boot_archinfo_load( void )
155{
156    archinfo_header_t* header = (archinfo_header_t*)ARCHINFO_BASE; 
157   
158    // Load file into memory
159    if (boot_fat32_load(ARCHINFO_PATHNAME, ARCHINFO_BASE, ARCHINFO_MAX_SIZE))
160    {
161        boot_printf("\n[BOOT ERROR]: boot_archinfo_load(): "
162                    "<%s> file not found\n",
163                    ARCHINFO_PATHNAME);
164        boot_exit();
165    }
166
167    if (header->signature != ARCHINFO_SIGNATURE)
168    {
169        boot_printf("\n[BOOT_ERROR]: boot_archinfo_load(): "
170                    "<%s> file signature should be %x\n",
171                    ARCHINFO_PATHNAME, ARCHINFO_SIGNATURE);
172        boot_exit();
173    }
174
175#if DEBUG_BOOT_INFO
176boot_printf("\n[BOOT INFO] in %s : file %s loaded at address = %x\n",
177            __FUNCTION__ , ARCHINFO_PATHNAME , ARCHINFO_BASE );
178#endif
179
180} // boot_archinfo_load()
181
182/**************************************************************************************
183 * This function loads the 'kernel.elf' file into the boot cluster memory buffer,
184 * analyzes it, and places the three kcode, kentry, kdata segments at their final
185 * physical adresses (defined the .elf file).       
186 * It set the global variables defining the kernel layout.
187 *************************************************************************************/
188static void boot_kernel_load( void )
189{
190    Elf32_Ehdr * elf_header;      // pointer on kernel.elf header. 
191    Elf32_Phdr * program_header;  // pointer on kernel.elf program header.
192    uint32_t     phdr_offset;     // program header offset in kernel.elf file.
193    uint32_t     segments_nb;     // number of segments in kernel.elf file.
194    uint32_t     seg_src_addr;    // segment address in kernel.elf file (source).
195    uint32_t     seg_paddr;       // segment local physical address of segment
196    uint32_t     seg_offset;      // segment offset in kernel.elf file
197    uint32_t     seg_filesz;      // segment size (bytes) in kernel.elf file
198    uint32_t     seg_memsz;       // segment size (bytes) in memory image.
199    bool_t       kcode_found;     // kcode segment found.
200    bool_t       kdata_found;     // kdata segment found.
201    bool_t       kentry_found;    // kentry segment found.
202    uint32_t     seg_id;          // iterator for segments loop.
203
204#if DEBUG_BOOT_ELF
205boot_printf("\n[BOOT INFO] %s enters for file %s at cycle %d\n",
206            __FUNCTION__ , KERNEL_PATHNAME , boot_get_proctime() );
207#endif
208
209    // Load kernel.elf file into memory buffer
210    if ( boot_fat32_load(KERNEL_PATHNAME, KERN_BASE, KERN_MAX_SIZE) )
211    {
212        boot_printf("\n[BOOT ERROR] in %s : <%s> file not found\n",
213                    KERNEL_PATHNAME);
214        boot_exit();
215    }
216
217    // get pointer to kernel.elf header 
218    elf_header = (Elf32_Ehdr*)KERN_BASE;
219
220    // check signature
221    if ((elf_header->e_ident[EI_MAG0] != ELFMAG0)   ||
222        (elf_header->e_ident[EI_MAG1] != ELFMAG1)   ||
223        (elf_header->e_ident[EI_MAG2] != ELFMAG2)   ||
224        (elf_header->e_ident[EI_MAG3] != ELFMAG3))
225    {
226        boot_printf("\n[BOOT_ERROR]: boot_kernel_load(): "
227                    "<%s> is not an ELF file\n",
228                    KERNEL_PATHNAME);
229        boot_exit();
230    }
231
232    // Get program header table offset and number of segments
233    phdr_offset     = elf_header->e_phoff;
234    segments_nb     = elf_header->e_phnum;
235
236    // Get program header table pointer
237    program_header  = (Elf32_Phdr*)(KERN_BASE + phdr_offset);
238
239    // loop on segments
240    kcode_found  = false;
241    kdata_found  = false;
242    kentry_found = false;
243    for (seg_id = 0; seg_id < segments_nb; seg_id++) 
244    {
245        if (program_header[seg_id].p_type == PT_LOAD)   // Found one loadable segment
246        {
247            // Get segment attributes.
248            seg_paddr    = program_header[seg_id].p_paddr;   
249            seg_offset   = program_header[seg_id].p_offset;
250            seg_filesz   = program_header[seg_id].p_filesz;
251            seg_memsz    = program_header[seg_id].p_memsz;
252
253            // get segment base address in buffer
254            seg_src_addr = (uint32_t)KERN_BASE + seg_offset;
255
256            // Load segment to its final physical memory address
257            boot_memcpy( (void*)seg_paddr, 
258                         (void*)seg_src_addr, 
259                         seg_filesz );
260
261#if DEBUG_BOOT_ELF
262boot_printf("\n[BOOT INFO] in %s for file %s : found loadable segment\n"
263            "   base = %x / size = %x\n",
264            __FUNCTION__ , KERNEL_PATHNAME , seg_paddr , seg_memsz );
265#endif
266
267            // Fill remaining memory with zero if (filesz < memsz).
268            if( seg_memsz < seg_filesz )
269            {
270                boot_memset( (void*)(seg_paddr + seg_filesz), 0, seg_memsz - seg_filesz);
271            }
272
273            // Note: we suppose that the 'kernel.elf' file contains exactly
274            // three loadable segments ktext, kentry, & kdata:
275            // - the kcode segment is read-only and base == KCODE_BASE
276            // - the kentry segment is read-only and base == KENTRY_BASE
277
278            if( ((program_header[seg_id].p_flags & PF_W) == 0) &&
279                 (program_header[seg_id].p_paddr == KCODE_BASE) )     // kcode segment
280            {
281                if( kcode_found )
282                {
283                    boot_printf("\n[BOOT_ERROR] in %s for file %s :\n"
284                                "   two kcode segments found\n",
285                                __FUNCTION__ , KERNEL_PATHNAME );
286                    boot_exit();
287                } 
288
289                kcode_found     = true;
290                seg_kcode_base = seg_paddr;
291                seg_kcode_size = seg_memsz;
292            }
293            else if( program_header[seg_id].p_paddr == KENTRY_BASE ) // kentry segment
294            {
295                if( kentry_found )
296                {
297                    boot_printf("\n[BOOT_ERROR] in %s for file %s :\n"
298                                "   two kentry segments found\n",
299                                __FUNCTION__ , KERNEL_PATHNAME );
300                    boot_exit();
301                } 
302
303                kentry_found     = true;
304                seg_kentry_base = seg_paddr;
305                seg_kentry_size = seg_memsz;
306            }
307            else                                                    // kdata segment
308            {
309                if( kdata_found )
310                {
311                    boot_printf("\n[BOOT_ERROR] in %s for file %s :\n"
312                                "   two loadable kdata segments found\n",
313                                __FUNCTION__ , KERNEL_PATHNAME );
314                    boot_exit();
315                } 
316
317                kdata_found     = true;
318                seg_kdata_base = seg_paddr;
319                seg_kdata_size = seg_memsz;
320            }
321        }
322    }
323
324    // check kcode & kdata segments found
325    if( kcode_found == false )
326    {
327        boot_printf("\n[BOOT_ERROR] in %s for file %s : seg_kcode not found\n",
328                    __FUNCTION__ , KERNEL_PATHNAME );
329        boot_exit();
330    }
331    if( kentry_found == false )
332    {
333        boot_printf("\n[BOOT_ERROR] in %s for file %s : seg_kentry not found\n",
334                    __FUNCTION__ , KERNEL_PATHNAME );
335        boot_exit();
336    }
337    if( kdata_found == false )
338    {
339        boot_printf("\n[BOOT_ERROR] in %s for file %s : seg_kdata not found\n",
340                    __FUNCTION__ , KERNEL_PATHNAME );
341        boot_exit();
342    }
343
344    // check segments sizes
345    if( seg_kentry_size > KENTRY_MAX_SIZE )
346    {
347        boot_printf("\n[BOOT_ERROR] in %s for file %s : seg_kentry too large\n",
348                    __FUNCTION__ , KERNEL_PATHNAME );
349        boot_exit();
350    }
351
352    if( (seg_kcode_size + seg_kdata_size) > KCODE_MAX_SIZE )
353    {
354        boot_printf("\n[BOOT_ERROR] in %s for file %s : seg_kcode + seg_kdata too large\n",
355                    __FUNCTION__ , KERNEL_PATHNAME );
356    }
357
358    // set entry point
359    kernel_entry = (uint32_t)elf_header->e_entry;
360
361#if DEBUG_BOOT_ELF
362boot_printf("\n[BOOT INFO] %s completed for file %s at cycle %d\n",
363            __FUNCTION__ , KERNEL_PATHNAME , boot_get_proctime() );
364#endif
365
366} // boot_kernel_load()
367
368/*************************************************************************************
369 * This function initializes the  boot_info_t structure for a given cluster.
370 * @ boot_info  : pointer to local boot_info_t structure 
371 * @ cxy        : cluster identifier                   
372 ************************************************************************************/
373static void boot_info_init( boot_info_t * boot_info,
374                            cxy_t         cxy )
375{
376    archinfo_header_t  * header;
377    archinfo_core_t    * core_base;     
378    archinfo_cluster_t * cluster_base; 
379    archinfo_device_t  * device_base;
380    archinfo_irq_t     * irq_base; 
381
382    archinfo_cluster_t * cluster; 
383    archinfo_cluster_t * my_cluster = NULL;   // target cluster
384    archinfo_cluster_t * io_cluster = NULL;   // cluster containing ext. peripherals
385
386    archinfo_core_t    * core;
387    uint32_t             core_id; 
388    archinfo_device_t  * device;
389    uint32_t             device_id;
390    archinfo_irq_t     * irq; 
391    uint32_t             irq_id;
392    uint32_t             end;
393    boot_device_t      * boot_dev; 
394
395    // get pointer on ARCHINFO header  and on the four arch_info arrays
396    header       = (archinfo_header_t*)ARCHINFO_BASE;
397    core_base    = archinfo_get_core_base   (header);
398    cluster_base = archinfo_get_cluster_base(header);
399    device_base  = archinfo_get_device_base (header);
400    irq_base     = archinfo_get_irq_base    (header);
401
402    // Initialize global platform parameters
403    boot_info->x_size       = header->x_size;
404    boot_info->y_size       = header->y_size;
405    boot_info->x_width      = header->x_width;
406    boot_info->y_width      = header->y_width;
407    boot_info->x_max        = header->x_size; // [FIXME]
408    boot_info->y_max        = header->name[5] == 'l' ? header->y_size - 1 : header->y_size; // [FIXME]
409    boot_info->paddr_width  = header->paddr_width;
410    boot_info->io_cxy       = header->io_cxy;
411
412    // Initialize kernel segments from global variables
413    boot_info->kcode_base  = seg_kcode_base;
414    boot_info->kcode_size  = seg_kcode_size;
415    boot_info->kdata_base  = seg_kdata_base;
416    boot_info->kdata_size  = seg_kdata_size;
417    boot_info->kentry_base = seg_kentry_base;
418    boot_info->kentry_size = seg_kentry_size;
419
420    /* Initialize all clusters as empty for now */
421    int x, y;
422    for ( x = 0; x < CONFIG_MAX_CLUSTERS_X; x++)
423    {
424        for ( x = 0; x < CONFIG_MAX_CLUSTERS_X; x++)
425        {
426            boot_info->cluster_info[x][y] = 0x0;
427        }
428    }
429
430    // loop on arch_info clusters to get relevant pointers
431    for (cluster =  cluster_base;
432         cluster < &cluster_base[header->x_size * header->y_size];
433         cluster++)
434    {
435        int x = cluster->cxy >> Y_WIDTH;
436        int y = cluster->cxy & ((1 << Y_WIDTH) - 1);
437
438        if( cluster->cxy  == cxy )            my_cluster = cluster;
439        if( cluster->cxy  == header->io_cxy ) {
440            io_cluster = cluster;
441            boot_info->cluster_info[x][y] |= CINFO_IS_IO;
442        }
443        if ( cluster->cores > 0 ) {
444            boot_info->cluster_info[x][y] |= CINFO_ACTIVE;
445        }
446    }
447
448    if( my_cluster == NULL ) 
449    {
450        boot_printf("\n[ERROR] in %s : cannot found cluster %x in arch_info\n",
451                    __FUNCTION__ , cxy );
452        boot_exit();
453    }
454
455    if( io_cluster == NULL ) 
456    {
457        boot_printf("\n[ERROR] in %s : cannot found io_cluster %x in arch_info\n",
458                    __FUNCTION__ , header->io_cxy );
459        boot_exit();
460    }
461
462    //////////////////////////////////////////////////////////
463    // initialize the boot_info array of external peripherals
464
465#if DEBUG_BOOT_INFO
466boot_printf("\n[BOOT INFO] %s : external peripherals at cycle %d\n",
467            __FUNCTION__ , boot_get_proctime() );
468#endif
469
470    device_id = 0;
471    for (device = &device_base[io_cluster->device_offset];
472         device < &device_base[io_cluster->device_offset + io_cluster->devices];
473         device++ )
474    {
475        if( device_id >= CONFIG_MAX_EXT_DEV ) 
476        {
477            boot_printf("\n[ERROR] in %s : too much external devices in arch_info\n",
478                        __FUNCTION__ );
479            boot_exit();
480        }
481       
482        // keep only external devices
483        if( (device->type != DEV_TYPE_RAM_SCL) &&
484            (device->type != DEV_TYPE_ICU_XCU) &&
485            (device->type != DEV_TYPE_MMC_TSR) &&
486            (device->type != DEV_TYPE_DMA_SCL) &&
487            (device->type != DEV_TYPE_TXT_MTY) &&
488            (device->type != DEV_TYPE_IOC_SPI) ) 
489        {
490            boot_dev = &boot_info->ext_dev[device_id];
491
492            boot_dev->type     = device->type;
493            boot_dev->base     = device->base;
494            boot_dev->channels = device->channels;
495            boot_dev->param0   = device->arg0;   
496            boot_dev->param1   = device->arg1;   
497            boot_dev->param2   = device->arg2;   
498            boot_dev->param3   = device->arg3;   
499            boot_dev->irqs     = device->irqs;   
500
501            device_id++;
502
503#if DEBUG_BOOT_INFO
504boot_printf("  - %s : base = %l / size = %l / channels = %d / irqs = %d\n",
505            device_type_str( device->type ) , device->base , device->size ,
506            device->channels , device->irqs );   
507#endif
508        }
509   
510        // handle IRQs for PIC
511        if (device->type == DEV_TYPE_PIC_TSR) 
512        {
513            for (irq_id = 0; irq_id < CONFIG_MAX_EXTERNAL_IRQS ; irq_id++)
514            {
515                boot_dev->irq[irq_id].valid  = 0;
516            }
517
518            for (irq = &irq_base[device->irq_offset];
519                 irq < &irq_base[device->irq_offset + device->irqs];
520                 irq++)
521            {
522                boot_dev->irq[irq->port].valid    = 1;
523                boot_dev->irq[irq->port].dev_type = irq->dev_type;
524                boot_dev->irq[irq->port].channel  = irq->channel;
525                boot_dev->irq[irq->port].is_rx    = irq->is_rx;
526
527#if DEBUG_BOOT_INFO
528boot_printf("    . irq_port = %d / source = %s / channel = %d / is_rx = %d\n",
529            irq->port , device_type_str( irq->dev_type ) , irq->channel , irq->is_rx );
530#endif
531            }
532        }
533    }   // end loop on io_cluster peripherals
534
535    // initialize number of external peripherals
536    boot_info->ext_dev_nr = device_id;
537
538    // Initialize cluster specific resources
539    boot_info->cxy  = my_cluster->cxy;
540
541#if DEBUG_BOOT_INFO
542boot_printf("\n[BOOT INFO] %s : cores in cluster %x\n", __FUNCTION__ , cxy );
543#endif
544
545    ////////////////////////////////////////
546    // Initialize array of core descriptors
547    core_id = 0;
548    for (core = &core_base[my_cluster->core_offset];
549         core < &core_base[my_cluster->core_offset + my_cluster->cores];
550         core++ )
551    {
552        boot_info->core[core_id].gid = (gid_t)core->gid;
553        boot_info->core[core_id].lid = (lid_t)core->lid; 
554        boot_info->core[core_id].cxy = (cxy_t)core->cxy;
555
556#if DEBUG_BOOT_INFO
557boot_printf("  - core_gid = %x : cxy = %x / lid = %d\n", 
558            core->gid , core->cxy , core->lid );
559#endif
560        core_id++;
561    }
562
563    // Initialize number of cores in my_cluster
564    boot_info->cores_nr = core_id;
565
566    //////////////////////////////////////////////////////////////////////
567    // initialise boot_info array of internal devices (RAM, ICU, MMC, DMA)
568
569#if DEBUG_BOOT_INFO
570boot_printf("\n[BOOT INFO] %s : internal peripherals in cluster %x\n", __FUNCTION__ , cxy );
571#endif
572
573    device_id = 0;
574    for (device = &device_base[my_cluster->device_offset];
575         device < &device_base[my_cluster->device_offset + my_cluster->devices];
576         device++ )
577    {
578        // keep only internal devices
579        if( (device->type == DEV_TYPE_RAM_SCL) ||
580            (device->type == DEV_TYPE_ICU_XCU) ||
581            (device->type == DEV_TYPE_MMC_TSR) ||
582            (device->type == DEV_TYPE_DMA_SCL) ||
583            (device->type == DEV_TYPE_TXT_MTY) ||
584            (device->type == DEV_TYPE_IOC_SPI) )
585        {
586            if (device->type == DEV_TYPE_RAM_SCL)   // RAM
587            {
588                // set number of physical memory pages
589                boot_info->pages_nr   = device->size >> CONFIG_PPM_PAGE_SHIFT;
590
591#if DEBUG_BOOT_INFO
592boot_printf("  - RAM : %x pages\n", boot_info->pages_nr );
593#endif
594            }
595            else                                    // ICU / MMC / DMA / MTY
596            {
597                if( device_id >= CONFIG_MAX_INT_DEV ) 
598                {
599                    boot_printf("\n[ERROR] in %s : too much internal devices in cluster %x\n",
600                                __FUNCTION__ , cxy );
601                    boot_exit();
602                }
603       
604                boot_dev = &boot_info->int_dev[device_id];
605
606                boot_dev->type     = device->type;
607                boot_dev->base     = device->base;
608                boot_dev->channels = device->channels;
609                boot_dev->param0   = device->arg0;   
610                boot_dev->param1   = device->arg1;   
611                boot_dev->param2   = device->arg2;   
612                boot_dev->param3   = device->arg3;   
613                boot_dev->irqs     = device->irqs; 
614
615                device_id++;
616
617#if DEBUG_BOOT_INFO
618boot_printf("  - %s : base = %l / size = %l / channels = %d / irqs = %d\n",
619            device_type_str( device->type ) , device->base , device->size ,
620            device->channels , device->irqs );   
621#endif
622
623                // handle IRQs for ICU
624                if (device->type == DEV_TYPE_ICU_XCU) 
625                {
626                    for (irq_id = 0; irq_id < CONFIG_MAX_INTERNAL_IRQS ; irq_id++)
627                    {
628                        boot_dev->irq[irq_id].valid  = 0;
629                    }
630
631                    for (irq = &irq_base[device->irq_offset];
632                         irq < &irq_base[device->irq_offset + device->irqs] ; irq++)
633                    {
634                        boot_dev->irq[irq->port].valid    = 1;
635                        boot_dev->irq[irq->port].dev_type = irq->dev_type;
636                        boot_dev->irq[irq->port].channel  = irq->channel;
637                        boot_dev->irq[irq->port].is_rx    = irq->is_rx;
638
639#if DEBUG_BOOT_INFO
640boot_printf("    . irq_port = %d / source = %s / channel = %d / is_rx = %d\n",
641            irq->port , device_type_str( irq->dev_type ) , irq->channel , irq->is_rx );
642#endif
643
644                    }
645                }
646            }
647        }
648    }  // end loop on local peripherals
649
650    // initialize number of internal peripherals
651    boot_info->int_dev_nr = device_id;
652
653   // Get the top address of the kernel segments
654    end = boot_info->kdata_base + boot_info->kdata_size;
655
656    // compute number of physical pages occupied by the kernel code
657    boot_info->pages_offset = ( (end & CONFIG_PPM_PAGE_MASK) == 0 ) ?
658                 (end >> CONFIG_PPM_PAGE_SHIFT) : (end >> CONFIG_PPM_PAGE_SHIFT) + 1;
659
660    // no reserved sones for TSAR architecture
661    boot_info->rsvd_nr = 0;
662
663    // set boot_info signature
664    boot_info->signature = BOOT_INFO_SIGNATURE;
665
666} // boot_info_init()
667
668/***********************************************************************************
669 * This function check the local boot_info_t structure for a given core.
670 * @ boot_info  : pointer to local 'boot_info_t' structure to be checked.
671 * @ lid        : core local identifier, index the core descriptor table.
672 **********************************************************************************/
673static void boot_check_core( boot_info_t * boot_info, 
674                             lid_t         lid)
675{
676    gid_t         gid;        // global hardware identifier of this core
677    boot_core_t * this;       // BOOT_INFO core descriptor of this core. 
678
679    // Get core hardware identifier
680    gid = (gid_t)boot_get_procid();
681
682    // get pointer on core descriptor
683    this = &boot_info->core[lid];
684
685    if ( (this->gid != gid) ||  (this->cxy != boot_info->cxy) )
686    {
687        boot_printf("\n[BOOT ERROR] in boot_check_core() :\n"
688                    " - boot_info cxy = %x\n"
689                    " - boot_info lid = %d\n"
690                    " - boot_info gid = %x\n"
691                    " - actual    gid = %x\n",
692                    this->cxy , this->lid , this->gid , gid );
693        boot_exit();
694    }
695
696} // boot_check_core()
697
698/*********************************************************************************
699 * This function is called by CP0 in cluster(0,0) to activate all other CP0s.
700 * It returns the number of CP0s actually activated.
701 ********************************************************************************/
702static uint32_t boot_wake_all_cp0s( void )
703{
704    archinfo_header_t*  header;         // Pointer on ARCHINFO header
705    archinfo_cluster_t* cluster_base;   // Pointer on ARCHINFO clusters base
706    archinfo_cluster_t* cluster;        // Iterator for loop on clusters
707    archinfo_device_t*  device_base;    // Pointer on ARCHINFO devices base
708    archinfo_device_t*  device;         // Iterator for loop on devices
709    uint32_t            cp0_nb = 0;     // CP0s counter
710
711    header       = (archinfo_header_t*)ARCHINFO_BASE;
712    cluster_base = archinfo_get_cluster_base(header);
713    device_base  = archinfo_get_device_base (header); 
714
715    // loop on all clusters
716    for (cluster = cluster_base;
717         cluster < &cluster_base[header->x_size * header->y_size];
718         cluster++)
719    {
720        // Skip boot cluster.
721        if (cluster->cxy == BOOT_CORE_CXY)
722            continue;
723           
724        // Skip clusters without core (thus without CP0).
725        if (cluster->cores == 0)
726            continue;
727
728        // Skip clusters without device (thus without XICU).
729        if (cluster->devices == 0)
730            continue;
731
732        // search XICU device associated to CP0, and send a WTI to activate it
733        for (device = &device_base[cluster->device_offset];
734             device < &device_base[cluster->device_offset + cluster->devices];
735             device++)
736        {
737            if (device->type == DEV_TYPE_ICU_XCU)
738            {
739
740#if DEBUG_BOOT_WAKUP
741boot_printf("\n[BOOT] core[%x,0] activated at cycle %d\n",
742            cluster->cxy , boot_get_proctime );
743#endif
744
745                boot_remote_sw((xptr_t)device->base, (uint32_t)boot_entry);
746                cp0_nb++;
747            }
748        }
749    }
750    return cp0_nb;
751
752} // boot_wake_cp0()
753
754/*********************************************************************************
755 * This function is called by all CP0 to activate the other CPi cores.
756 * @ boot_info  : pointer to local 'boot_info_t' structure.
757 *********************************************************************************/
758static void boot_wake_local_cores(boot_info_t * boot_info)
759{
760    unsigned int     core_id;       
761
762    // get pointer on XCU device descriptor in boot_info
763    boot_device_t *  xcu = &boot_info->int_dev[0];
764 
765    // loop on cores
766    for (core_id = 1; core_id < boot_info->cores_nr; core_id++)
767    {
768
769#if DEBUG_BOOT_WAKUP
770boot_printf("\n[BOOT] core[%x,%d] activated at cycle %d\n",
771             boot_info->cxy , core_id , boot_get_proctime() );
772#endif
773        // send an IPI
774        boot_remote_sw( (xptr_t)(xcu->base + (core_id << 2)) , (uint32_t)boot_entry ); 
775    }
776} // boot_wake_local_cores()
777
778
779/*********************************************************************************
780 * This main function of the boot-loader is called by the  boot_entry() 
781 * function, and executed by all cores.
782 * The arguments values are computed by the boot_entry code.
783 * @ lid    : core local identifier,
784 * @ cxy    : cluster identifier,
785 *********************************************************************************/
786void boot_loader( lid_t lid,
787                  cxy_t cxy )
788{
789    boot_info_t * boot_info;       // pointer on local boot_info_t structure
790
791    if (lid == 0) 
792    {
793        /****************************************************
794         * PHASE A : only CP0 in boot cluster executes it
795         ***************************************************/
796        if (cxy == BOOT_CORE_CXY)
797        {
798            boot_printf("\n[BOOT] core[%x,%d] enters at cycle %d\n",
799                        cxy , lid , boot_get_proctime() );
800
801            // Initialize IOC driver
802            if      (USE_IOC_BDV) boot_bdv_init();
803            else if (USE_IOC_HBA) boot_hba_init();
804            // else if (USE_IOC_SDC) boot_sdc_init();
805            else if (USE_IOC_SPI) boot_spi_init();
806            else if (!USE_IOC_RDK)
807            {
808                boot_printf("\n[BOOT ERROR] in %s : no IOC driver\n");
809                boot_exit();
810            }
811
812            // Initialize FAT32.
813            boot_fat32_init();
814
815            // Load the 'kernel.elf' file into memory from IOC, and set   
816            // the global variables defining the kernel layout     
817            boot_kernel_load();
818
819            boot_printf("\n[BOOT] core[%x,%d] loaded kernel at cycle %d\n",
820                        cxy , lid , boot_get_proctime() );
821
822            // Load the arch_info.bin file into memory.
823            boot_archinfo_load();
824
825            // Get local boot_info_t structure base address.
826            // It is the first structure in the .kdata segment.
827            boot_info = (boot_info_t *)seg_kdata_base;
828
829            // Initialize local boot_info_t structure.
830            boot_info_init( boot_info , cxy );
831
832            // check boot_info signature
833            if (boot_info->signature != BOOT_INFO_SIGNATURE)
834            {
835                boot_printf("\n[BOOT ERROR] in %s reported by core[%x,%d]\n"
836                            "  illegal boot_info signature / should be %x\n",
837                            __FUNCTION__ , cxy , lid , BOOT_INFO_SIGNATURE );
838                boot_exit();
839            }
840
841            boot_printf("\n[BOOT] core[%x,%d] loaded arch_info at cycle %d\n",
842                        cxy , lid , boot_get_proctime() );
843
844            // Check core information.
845            boot_check_core(boot_info, lid);
846
847            // Activate other CP0s / get number of active CP0s
848            active_cp0s_nr = boot_wake_all_cp0s() + 1;
849
850            // Wait until all clusters (i.e all CP0s) ready to enter kernel.
851            boot_remote_barrier( XPTR( BOOT_CORE_CXY , &global_barrier ) ,
852                                 active_cp0s_nr );
853
854            // activate other local cores
855            boot_wake_local_cores( boot_info );
856
857// display address extensions
858// uint32_t cp2_data_ext;
859// uint32_t cp2_ins_ext;
860// asm volatile( "mfc2   %0,  $24" : "=&r" (cp2_data_ext) );
861// asm volatile( "mfc2   %0,  $25" : "=&r" (cp2_ins_ext) );
862// boot_printf("\n[BOOT] core[%x,%d] CP2_DATA_EXT = %x / CP2_INS_EXT = %x\n",
863// cxy , lid , cp2_data_ext , cp2_ins_ext );
864
865            // Wait until all local cores in cluster ready
866            boot_remote_barrier( XPTR( cxy , &local_barrier ) , 
867                                 boot_info->cores_nr );
868        }
869        /******************************************************************
870         * PHASE B : all CP0s other than CP0 in boot cluster execute it
871         *****************************************************************/
872        else
873        {
874            // at this point, all INSTRUCTION address extension registers
875            // point on cluster(0,0), but the DATA extension registers point
876            // already on the local cluster to use the local stack.
877            // To access the bootloader global variables we must first copy
878            // the boot code (data and instructions) in the local cluster.
879            boot_remote_memcpy( XPTR( cxy           , BOOT_BASE ),
880                                XPTR( BOOT_CORE_CXY , BOOT_BASE ),
881                                BOOT_MAX_SIZE );
882
883            // from now, it is safe to refer to the boot code global variables
884            boot_printf("\n[BOOT] core[%x,%d] replicated boot code at cycle %d\n",
885                        cxy , lid , boot_get_proctime() );
886
887                        // switch to the INSTRUCTION local memory space, to avoid contention.
888            // asm volatile("mtc2  %0, $25" :: "r"(cxy));
889
890            // Copy the arch_info.bin file into the local memory.
891            boot_remote_memcpy(XPTR(cxy,           ARCHINFO_BASE),
892                               XPTR(BOOT_CORE_CXY, ARCHINFO_BASE),
893                               ARCHINFO_MAX_SIZE );
894
895            boot_printf("\n[BOOT] core[%x,%d] replicated arch_info at cycle %d\n",
896                        cxy , lid , boot_get_proctime() );
897
898            // Copy the kcode segment into local memory
899            boot_remote_memcpy( XPTR( cxy           , seg_kcode_base ),
900                                XPTR( BOOT_CORE_CXY , seg_kcode_base ),
901                                seg_kcode_size );
902
903            // Copy the kdata segment into local memory
904            boot_remote_memcpy( XPTR( cxy           , seg_kdata_base ),
905                                XPTR( BOOT_CORE_CXY , seg_kdata_base ),
906                                seg_kdata_size );
907
908            // Copy the kentry segment into local memory
909            boot_remote_memcpy( XPTR( cxy           , seg_kentry_base ),
910                                XPTR( BOOT_CORE_CXY , seg_kentry_base ),
911                                seg_kentry_size );
912
913            boot_printf("\n[BOOT] core[%x,%d] replicated kernel code at cycle %d\n",
914                        cxy , lid , boot_get_proctime() );
915
916            // Get local boot_info_t structure base address.
917            boot_info = (boot_info_t*)seg_kdata_base;
918
919            // Initialize local boot_info_t structure.
920            boot_info_init( boot_info , cxy );
921
922            // Check core information.
923            boot_check_core( boot_info , lid );
924
925            // get number of active clusters from BOOT_CORE cluster
926            uint32_t count = boot_remote_lw( XPTR( BOOT_CORE_CXY , &active_cp0s_nr ) );
927
928            // Wait until all clusters (i.e all CP0s) ready to enter kernel
929            boot_remote_barrier( XPTR( BOOT_CORE_CXY , &global_barrier ) , count );
930
931            // activate other local cores
932            boot_wake_local_cores( boot_info );
933
934// display address extensions
935// uint32_t cp2_data_ext;
936// uint32_t cp2_ins_ext;
937// asm volatile( "mfc2   %0,  $24" : "=&r" (cp2_data_ext) );
938// asm volatile( "mfc2   %0,  $25" : "=&r" (cp2_ins_ext) );
939// boot_printf("\n[BOOT] core[%x,%d] CP2_DATA_EXT = %x / CP2_INS_EXT = %x\n",
940// cxy , lid , cp2_data_ext , cp2_ins_ext );
941
942            // Wait until all local cores in cluster ready
943            boot_remote_barrier( XPTR( cxy , &local_barrier ) , 
944                                 boot_info->cores_nr );
945        }
946    }
947    else
948    {
949        /***************************************************************
950         * PHASE C: all non CP0 cores in all clusters execute it
951         **************************************************************/
952
953        // Switch to the INSTRUCTIONS local memory space
954        // to avoid contention at the boot cluster.
955        // asm volatile("mtc2  %0, $25" :: "r"(cxy));
956
957        // Get local boot_info_t structure base address.
958        boot_info = (boot_info_t *)seg_kdata_base;
959
960        // Check core information
961        boot_check_core(boot_info, lid);
962
963// display address extensions
964// uint32_t cp2_data_ext;
965// uint32_t cp2_ins_ext;
966// asm volatile( "mfc2   %0,  $24" : "=&r" (cp2_data_ext) );
967// asm volatile( "mfc2   %0,  $25" : "=&r" (cp2_ins_ext) );
968// boot_printf("\n[BOOT] core[%x,%d] CP2_DATA_EXT = %x / CP2_INS_EXT = %x\n",
969// cxy , lid , cp2_data_ext , cp2_ins_ext );
970
971        // Wait until all local cores in cluster ready
972        boot_remote_barrier( XPTR( cxy , &local_barrier ) , boot_info->cores_nr );
973    }
974
975    // Each core initialise the following registers before jumping to kernel:
976    // - sp_29    : stack pointer on idle thread,
977    // - c0_sr    : reset BEV bit
978    // - a0_04    : pointer on boot_info structure
979    // - c0_ebase : kentry_base(and jump to kernel_entry.
980
981    // The array of idle-thread descriptors is allocated in the kdata segment,
982    // just after the boot_info structure
983    uint32_t sp;
984    uint32_t base;
985    uint32_t offset = sizeof( boot_info_t );
986    uint32_t pmask  = CONFIG_PPM_PAGE_MASK;
987    uint32_t psize  = CONFIG_PPM_PAGE_SIZE;
988
989    // compute base address of idle thread descriptors array
990    if( offset & pmask ) base = seg_kdata_base + (offset & ~pmask) + psize;
991    else                 base = seg_kdata_base + offset;
992
993    // compute stack pointer
994    sp = base + ((lid + 1) * CONFIG_THREAD_DESC_SIZE) - 16;
995
996    asm volatile( "mfc0  $27,  $12           \n"
997                  "lui   $26,  0xFFBF        \n"
998                  "ori   $26,  $26,  0xFFFF  \n"
999                  "and   $27,  $27,  $26     \n"
1000                  "mtc0  $27,  $12           \n"
1001                  "move  $4,   %0            \n"
1002                  "move  $29,  %1            \n"
1003                  "mtc0  %2,   $15,  1       \n"
1004                  "jr    %3                  \n"
1005                  :
1006                  : "r"(boot_info) ,
1007                    "r"(sp) ,
1008                    "r"(boot_info->kentry_base) ,
1009                    "r"(kernel_entry) 
1010                  : "$26" , "$27" , "$29" , "$4" );
1011
1012
1013} // boot_loader()
Note: See TracBrowser for help on using the repository browser.