source: soft/giet_vm/boot/boot_init.c @ 246

Last change on this file since 246 was 246, checked in by meunier, 11 years ago

Cosmétique + gestion du reset de l'irq du timer ou de l'xicu lors d'un task_switch

File size: 70.2 KB
RevLine 
[189]1//////////////////////////////////////////////////////////////////////////////////
2// File     : boot_init.c
3// Date     : 01/04/2012
4// Author   : alain greiner
5// Copyright (c) UPMC-LIP6
6///////////////////////////////////////////////////////////////////////////////////
7// The boot_init.c file is part of the GIET-VM nano-kernel.
8// This code is executed in the boot phase by proc[0] to initialize the
[238]9// peripherals and the kernel data structures:
[189]10// - pages tables for the various vspaces
11// - shedulers for processors (including the tasks contexts and interrupt vectors)
12//
[238]13// This nano-kernel has been written for the MIPS32 processor.
14// The virtual adresses are on 32 bits and use the (unsigned int) type, but the
15// physicals addresses can have up to 40 bits, and use the  (unsigned long long) type.
16//
[189]17// The GIET-VM uses the paged virtual memory and the MAPPING_INFO binary file
18// to provides two services:
19// 1) classical memory protection, when several independant applications compiled
20//    in different virtual spaces are executing on the same hardware platform.
21// 2) data placement in NUMA architectures, when we want to control the placement
22//    of the software objects (virtual segments) on the physical memory banks.
23//
24// The MAPPING_INFO binary data structure must be loaded in the the seg_boot_mapping
25// segment (at address seg_mapping_base).
[238]26// This MAPPING_INFO data structure defines
27// - the hardware architecture: number of clusters, number or processors,
28//   size of the memory segments, and peripherals in each cluster.
29// - The structure of the various multi-threaded software applications:
30//   number of tasks, communication channels.
31// - The mapping: placement of virtual objects (vobj) in the virtual segments (vseg),
32//   placement of virtual segments (vseg) in the physical segments (pseg), placement
33//   of software tasks on the processors,
[189]34//
[199]35// The page table are statically build in the boot phase, and they do not
[189]36// change during execution. The GIET uses only 4 Kbytes pages.
37// As most applications use only a limited number of segments, the number of PT2s
38// actually used by a given virtual space is generally smaller than 2048, and is
[199]39// computed during the boot phase.
[189]40// The max number of virtual spaces (GIET_NB_VSPACE_MAX) is a configuration parameter.
41//
[238]42// Each page table (one page table per virtual space) is monolithic, and contains
43// one PT1 and up to (GIET_NB_PT2_MAX) PT2s. The PT1 is addressed using the ix1 field
[189]44// (11 bits) of the VPN, and the selected PT2 is addressed using the ix2 field (9 bits).
[238]45// - PT1[2048] : a first 8K aligned array of unsigned int, indexed by (ix1) field of VPN.
[189]46//   Each entry in the PT1 contains a 32 bits PTD. The MSB bit PTD[31] is
47//   the PTD valid bit, and LSB bits PTD[19:0] are the 20 MSB bits of the physical base
48//   address of the selected PT2.
49//   The PT1 contains 2048 PTD of 4 bytes => 8K bytes.
50// - PT2[1024][GIET_NB_PT2_MAX] : an array of array of unsigned int.
[238]51//   Each PT2[1024] must be 4K aligned, each entry in a PT2 contains two unsigned int:
[189]52//   the first word contains the protection flags, and the second word contains the PPN.
53//   Each PT2 contains 512 PTE2 of 8bytes => 4K bytes.
54// The total size of a page table is finally = 8K + (GIET_NB_PT2_MAX)*4K bytes.
55////////////////////////////////////////////////////////////////////////////////////
56
57#include <common.h>
58#include <mips32_registers.h>
59#include <giet_config.h>
60#include <mapping_info.h>
61#include <mwmr_channel.h>
62#include <barrier.h>
[228]63#include <memspace.h>
[189]64#include <irq_handler.h>
65#include <ctx_handler.h>
66#include <vm_handler.h>
67#include <hwr_mapping.h>
68
69#include <stdarg.h>
70
[228]71#if !defined(NB_CLUSTERS)
[189]72# error The NB_CLUSTERS value must be defined in the 'giet_config.h' file !
73#endif
74
[228]75#if !defined(NB_PROCS_MAX)
[189]76# error The NB_PROCS_MAX value must be defined in the 'giet_config.h' file !
77#endif
78
[228]79#if !defined(GIET_NB_VSPACE_MAX)
[189]80# error The GIET_NB_VSPACE_MAX value must be defined in the 'giet_config.h' file !
81#endif
82
83////////////////////////////////////////////////////////////////////////////
84//      Global variables for boot code
[238]85// Both the page tables for the various virtual spaces, and the schedulers
86// for the processors are physically distributed on the clusters.
87// These global variables are just arrays of pointers.
[189]88////////////////////////////////////////////////////////////////////////////
89
[238]90// Page table addresses arrays
[245]91__attribute__((section (".wdata"))) 
[238]92paddr_t      boot_ptabs_paddr[GIET_NB_VSPACE_MAX];
[245]93
94__attribute__((section (".wdata"))) 
[238]95unsigned int boot_ptabs_vaddr[GIET_NB_VSPACE_MAX];
[189]96
[238]97// Scheduler pointers array (virtual addresses)
[245]98__attribute__((section (".wdata"))) 
[238]99static_scheduler_t* boot_schedulers[NB_CLUSTERS * NB_PROCS_MAX];
[189]100
101// Next free PT2 index array
[245]102__attribute__((section (".wdata"))) 
[228]103unsigned int boot_next_free_pt2[GIET_NB_VSPACE_MAX] =
104{ [0 ... GIET_NB_VSPACE_MAX - 1] = 0 };
[189]105
106// Max PT2 index
[245]107__attribute__((section (".wdata"))) 
[228]108unsigned int boot_max_pt2[GIET_NB_VSPACE_MAX] =
109{ [0 ... GIET_NB_VSPACE_MAX - 1] = 0 };
[189]110
111
112//////////////////////////////////////////////////////////////////////////////
113// boot_procid()
114//////////////////////////////////////////////////////////////////////////////
[238]115inline unsigned int boot_procid() 
116{
[189]117    unsigned int ret;
[228]118    asm volatile ("mfc0 %0, $15, 1":"=r" (ret));
[189]119    return (ret & 0x3FF);
120}
[228]121
[189]122//////////////////////////////////////////////////////////////////////////////
123// boot_proctime()
124//////////////////////////////////////////////////////////////////////////////
[238]125inline unsigned int boot_proctime() 
126{
[189]127    unsigned int ret;
[228]128    asm volatile ("mfc0 %0, $9":"=r" (ret));
[189]129    return ret;
130}
[228]131
[189]132//////////////////////////////////////////////////////////////////////////////
133// boot_exit()
134//////////////////////////////////////////////////////////////////////////////
[238]135void boot_exit() 
136{
137    while (1) { asm volatile ("nop"); }
[189]138}
[228]139
[189]140//////////////////////////////////////////////////////////////////////////////
141// boot_eret()
142// The address of this function is used to initialise the return address (RA)
143// in all task contexts (when the task has never been executed.
144/////////////////////////////////"/////////////////////////////////////////////
[238]145void boot_eret() 
146{
[228]147    asm volatile ("eret");
[189]148}
[228]149
[238]150////////////////////////////////////////////////////////////////////////////
151// boot_physical_read()
152// This function makes a physical read access to a 32 bits word in memory,
153// after a temporary DTLB de-activation and paddr extension.
154////////////////////////////////////////////////////////////////////////////
155unsigned int boot_physical_read(paddr_t paddr) 
156{
[215]157    unsigned int value;
[246]158    unsigned int lsb = (unsigned int) paddr;
159    unsigned int msb = (unsigned int) (paddr >> 32);
[215]160
[238]161    asm volatile(
162            "mfc2   $2,     $1                 \n"     /* $2 <= MMU_MODE   */
163            "andi   $3,     $2,        0xb     \n"
164            "mtc2   $3,     $1                 \n"     /* DTLB off         */   
[228]165
[238]166            "mtc2   %2,     $24                \n"     /* PADDR_EXT <= msb */   
167            "lw     %0,     0(%1)              \n"     /* value <= *paddr  */
168            "mtc2   $0,     $24                \n"     /* PADDR_EXT <= 0   */   
[215]169
[238]170            "mtc2   $2,     $1                 \n"     /* restore MMU_MODE */
171            : "=r" (value)
172            : "r" (lsb), "r" (msb)
173            : "$2", "$3");
[215]174    return value;
175}
176
[238]177////////////////////////////////////////////////////////////////////////////
178// boot_physical_write()
179// This function makes a physical write access to a 32 bits word in memory,
180// after a temporary DTLB de-activation and paddr extension.
181////////////////////////////////////////////////////////////////////////////
182void boot_physical_write(paddr_t      paddr, 
183                         unsigned int value) 
184{
185    unsigned int lsb = (unsigned int)paddr;
186    unsigned int msb = (unsigned int)(paddr >> 32);
[228]187
[238]188    asm volatile(
189            "mfc2   $2,     $1                 \n"     /* $2 <= MMU_MODE   */
190            "andi   $3,     $2,        0xb     \n"
191            "mtc2   $3,     $1                 \n"     /* DTLB off         */   
[189]192
[238]193            "mtc2   %2,     $24                \n"     /* PADDR_EXT <= msb */   
194            "sw     %0,     0(%1)              \n"     /* *paddr <= value  */
195            "mtc2   $0,     $24                \n"     /* PADDR_EXT <= 0   */   
[228]196
[238]197            "mtc2   $2,     $1                 \n"     /* restore MMU_MODE */
[228]198            :
[238]199            : "r" (value), "r" (lsb), "r" (msb)
200            : "$2", "$3");
[189]201}
[228]202
[189]203//////////////////////////////////////////////////////////////////////////////
204// boot_set_mmu_ptpr()
205// This function set a new value for the MMU PTPR register.
206//////////////////////////////////////////////////////////////////////////////
[238]207inline void boot_set_mmu_ptpr(unsigned int val) 
208{
[228]209    asm volatile ("mtc2  %0, $0"::"r" (val));
[189]210}
211
212//////////////////////////////////////////////////////////////////////////////
213// boot_set_mmu_mode()
214// This function set a new value for the MMU MODE register.
215//////////////////////////////////////////////////////////////////////////////
[238]216inline void boot_set_mmu_mode(unsigned int val) 
217{
[228]218    asm volatile ("mtc2  %0, $1"::"r" (val));
[189]219}
[228]220
[189]221////////////////////////////////////////////////////////////////////////////
222// boot_puts()
[238]223// display a string on TTY0
[189]224////////////////////////////////////////////////////////////////////////////
[238]225void boot_puts(const char * buffer) 
226{
[228]227    unsigned int *tty_address = (unsigned int *) &seg_tty_base;
[189]228    unsigned int n;
229
[238]230    for (n = 0; n < 100; n++) 
231    {
232        if (buffer[n] == 0)  break; 
[228]233        tty_address[TTY_WRITE] = (unsigned int) buffer[n];
[189]234    }
[228]235}
236
[189]237////////////////////////////////////////////////////////////////////////////
[204]238// boot_putx()
[238]239// display a 32 bits unsigned int as an hexadecimal string on TTY0
[189]240////////////////////////////////////////////////////////////////////////////
[238]241void boot_putx(unsigned int val) 
242{
[228]243    static const char HexaTab[] = "0123456789ABCDEF";
244    char buf[11];
245    unsigned int c;
[189]246
[228]247    buf[0] = '0';
248    buf[1] = 'x';
[189]249    buf[10] = 0;
250
[238]251    for (c = 0; c < 8; c++) 
252    {
[228]253        buf[9 - c] = HexaTab[val & 0xF];
[189]254        val = val >> 4;
255    }
256    boot_puts(buf);
257}
[228]258
[238]259////////////////////////////////////////////////////////////////////////////
260// boot_putl()
261// display a 64 bits unsigned long as an hexadecimal string on TTY0
262////////////////////////////////////////////////////////////////////////////
263void boot_putl(paddr_t val) 
264{
265    static const char HexaTab[] = "0123456789ABCDEF";
266    char buf[19];
267    unsigned int c;
[228]268
[238]269    buf[0] = '0';
270    buf[1] = 'x';
271    buf[18] = 0;
272
273    for (c = 0; c < 16; c++) 
274    {
275        buf[17 - c] = HexaTab[(unsigned int)val & 0xF];
276        val = val >> 4;
277    }
278    boot_puts(buf);
279}
280
[204]281////////////////////////////////////////////////////////////////////////////
282// boot_putd()
[238]283// display a 32 bits unsigned int as a decimal string on TTY0
[204]284////////////////////////////////////////////////////////////////////////////
[238]285void boot_putd(unsigned int val) 
286{
[228]287    static const char DecTab[] = "0123456789";
288    char buf[11];
289    unsigned int i;
290    unsigned int first;
[189]291
[204]292    buf[10] = 0;
293
[238]294    for (i = 0; i < 10; i++) 
295    {
296        if ((val != 0) || (i == 0)) 
297        {
[228]298            buf[9 - i] = DecTab[val % 10];
299            first = 9 - i;
[204]300        }
[238]301        else 
302        {
[204]303            break;
304        }
305        val /= 10;
306    }
[228]307    boot_puts(&buf[first]);
[204]308}
309
[189]310/////////////////////////////////////////////////////////////////////////////
311//  mapping_info data structure access functions
312/////////////////////////////////////////////////////////////////////////////
[238]313inline mapping_cluster_t *boot_get_cluster_base(mapping_header_t * header) 
314{
[228]315    return (mapping_cluster_t *) ((char *) header + MAPPING_HEADER_SIZE);
[189]316}
317/////////////////////////////////////////////////////////////////////////////
[238]318inline mapping_pseg_t *boot_get_pseg_base(mapping_header_t * header) 
319{
[228]320    return (mapping_pseg_t *) ((char *) header +
321            MAPPING_HEADER_SIZE +
322            MAPPING_CLUSTER_SIZE * header->clusters);
[189]323}
324/////////////////////////////////////////////////////////////////////////////
[238]325inline mapping_vspace_t *boot_get_vspace_base(mapping_header_t * header) 
326{
[228]327    return (mapping_vspace_t *) ((char *) header +
328            MAPPING_HEADER_SIZE +
329            MAPPING_CLUSTER_SIZE * header->clusters +
330            MAPPING_PSEG_SIZE * header->psegs);
[189]331}
332/////////////////////////////////////////////////////////////////////////////
[238]333inline mapping_vseg_t *boot_get_vseg_base(mapping_header_t * header) 
334{
[228]335    return (mapping_vseg_t *) ((char *) header +
336            MAPPING_HEADER_SIZE +
337            MAPPING_CLUSTER_SIZE * header->clusters +
338            MAPPING_PSEG_SIZE * header->psegs +
339            MAPPING_VSPACE_SIZE * header->vspaces);
[189]340}
341/////////////////////////////////////////////////////////////////////////////
[238]342inline mapping_vobj_t *boot_get_vobj_base(mapping_header_t * header) 
343{
[228]344    return (mapping_vobj_t *) ((char *) header +
345            MAPPING_HEADER_SIZE +
346            MAPPING_CLUSTER_SIZE * header->clusters +
347            MAPPING_PSEG_SIZE * header->psegs +
348            MAPPING_VSPACE_SIZE * header->vspaces +
349            MAPPING_VSEG_SIZE * header->vsegs);
[189]350}
351/////////////////////////////////////////////////////////////////////////////
[238]352inline mapping_task_t *boot_get_task_base(mapping_header_t * header) 
353{
[228]354    return (mapping_task_t *) ((char *) header +
355            MAPPING_HEADER_SIZE +
356            MAPPING_CLUSTER_SIZE * header->clusters +
357            MAPPING_PSEG_SIZE * header->psegs +
358            MAPPING_VSPACE_SIZE * header->vspaces +
359            MAPPING_VSEG_SIZE * header->vsegs +
360            MAPPING_VOBJ_SIZE * header->vobjs);
[189]361}
362/////////////////////////////////////////////////////////////////////////////
[238]363inline mapping_proc_t *boot_get_proc_base(mapping_header_t * header) 
364{
[228]365    return (mapping_proc_t *) ((char *) header +
366            MAPPING_HEADER_SIZE +
367            MAPPING_CLUSTER_SIZE * header->clusters +
368            MAPPING_PSEG_SIZE * header->psegs +
369            MAPPING_VSPACE_SIZE * header->vspaces +
370            MAPPING_VSEG_SIZE * header->vsegs +
371            MAPPING_VOBJ_SIZE * header->vobjs +
372            MAPPING_TASK_SIZE * header->tasks);
[189]373}
374/////////////////////////////////////////////////////////////////////////////
[238]375inline mapping_irq_t *boot_get_irq_base(mapping_header_t * header) 
376{
[228]377    return (mapping_irq_t *) ((char *) header +
378            MAPPING_HEADER_SIZE +
379            MAPPING_CLUSTER_SIZE * header->clusters +
380            MAPPING_PSEG_SIZE * header->psegs +
381            MAPPING_VSPACE_SIZE * header->vspaces +
382            MAPPING_VSEG_SIZE * header->vsegs +
383            MAPPING_VOBJ_SIZE * header->vobjs +
384            MAPPING_TASK_SIZE * header->tasks +
385            MAPPING_PROC_SIZE * header->procs);
[189]386}
387/////////////////////////////////////////////////////////////////////////////
[238]388inline mapping_coproc_t *boot_get_coproc_base(mapping_header_t * header) 
389{
[228]390    return (mapping_coproc_t *) ((char *) header +
391            MAPPING_HEADER_SIZE +
392            MAPPING_CLUSTER_SIZE * header->clusters +
393            MAPPING_PSEG_SIZE * header->psegs +
394            MAPPING_VSPACE_SIZE * header->vspaces +
395            MAPPING_VOBJ_SIZE * header->vobjs +
396            MAPPING_VSEG_SIZE * header->vsegs +
397            MAPPING_TASK_SIZE * header->tasks +
398            MAPPING_PROC_SIZE * header->procs +
399            MAPPING_IRQ_SIZE * header->irqs);
[189]400}
401///////////////////////////////////////////////////////////////////////////////////
[238]402inline mapping_cp_port_t *boot_get_cp_port_base(mapping_header_t * header) 
403{
[228]404    return (mapping_cp_port_t *) ((char *) header +
405            MAPPING_HEADER_SIZE +
406            MAPPING_CLUSTER_SIZE * header->clusters +
407            MAPPING_PSEG_SIZE * header->psegs +
408            MAPPING_VSPACE_SIZE * header->vspaces +
409            MAPPING_VOBJ_SIZE * header->vobjs +
410            MAPPING_VSEG_SIZE * header->vsegs +
411            MAPPING_TASK_SIZE * header->tasks +
412            MAPPING_PROC_SIZE * header->procs +
413            MAPPING_IRQ_SIZE * header->irqs +
414            MAPPING_COPROC_SIZE * header->coprocs);
[189]415}
416///////////////////////////////////////////////////////////////////////////////////
[238]417inline mapping_periph_t *boot_get_periph_base(mapping_header_t * header) 
418{
[228]419    return (mapping_periph_t *) ((char *) header +
420            MAPPING_HEADER_SIZE +
421            MAPPING_CLUSTER_SIZE * header->clusters +
422            MAPPING_PSEG_SIZE * header->psegs +
423            MAPPING_VSPACE_SIZE * header->vspaces +
424            MAPPING_VOBJ_SIZE * header->vobjs +
425            MAPPING_VSEG_SIZE * header->vsegs +
426            MAPPING_TASK_SIZE * header->tasks +
427            MAPPING_PROC_SIZE * header->procs +
428            MAPPING_IRQ_SIZE * header->irqs +
429            MAPPING_COPROC_SIZE * header->coprocs +
430            MAPPING_CP_PORT_SIZE * header->cp_ports);
[189]431}
432
433//////////////////////////////////////////////////////////////////////////////
434//     boot_pseg_get()
435// This function returns the pointer on a physical segment
436// identified  by the pseg index.
437//////////////////////////////////////////////////////////////////////////////
[238]438mapping_pseg_t *boot_pseg_get(unsigned int seg_id) 
439{
[228]440    mapping_header_t * header = (mapping_header_t *) & seg_mapping_base;
441    mapping_pseg_t * pseg = boot_get_pseg_base(header);
[189]442
443    // checking argument
[238]444    if (seg_id >= header->psegs) 
445    {
[189]446        boot_puts("\n[BOOT ERROR] : seg_id argument too large\n");
447        boot_puts("               in function boot_pseg_get()\n");
448        boot_exit();
449    }
450
[228]451    return &pseg[seg_id];
[238]452} 
[189]453
454//////////////////////////////////////////////////////////////////////////////
455// boot_add_pte()
[238]456// This function registers a new PTE in the page table defined
[189]457// by the vspace_id argument, and updates both PT1 and PT2.
458// A new PT2 is used when required.
459// As the set of PT2s is implemented as a fixed size array (no dynamic
460// allocation), this function checks a possible overflow of the PT2 array.
461//////////////////////////////////////////////////////////////////////////////
[228]462void boot_add_pte(unsigned int vspace_id,
[238]463                  unsigned int vpn, 
464                  unsigned int flags, 
465                  unsigned int ppn,
466                  unsigned int verbose) 
467{
[228]468    unsigned int ix1;
469    unsigned int ix2;
[238]470    paddr_t      pt1_pbase;     // PT1 physical base address
471    paddr_t      pt2_pbase;     // PT2 physical base address
472    paddr_t      pte_paddr;     // PTE physucal address
473    unsigned int pt2_id;        // PT2 index
474    unsigned int ptd;           // PTD : entry in PT1
475    unsigned int max_pt2;       // max number of PT2s for a given vspace
[189]476
[228]477    ix1 = vpn >> 9;         // 11 bits
478    ix2 = vpn & 0x1FF;      //  9 bits
[189]479
480    // check that the boot_max_pt2[vspace_id] has been set
[238]481    max_pt2 = boot_max_pt2[vspace_id];
[189]482
[238]483    if (max_pt2 == 0) 
484    {
485        boot_puts("Undefined page table for vspace ");
[204]486        boot_putd(vspace_id);
[189]487        boot_puts("\n");
488        boot_exit();
489    }
490
[246]491
[238]492    // get page table physical base address
493    pt1_pbase = boot_ptabs_paddr[vspace_id];
494
495    // get ptd in PT1
[246]496    ptd = boot_physical_read(pt1_pbase + 4 * ix1);
[238]497
498    if ((ptd & PTE_V) == 0)    // invalid PTD: compute PT2 base address,
499                               // and set a new PTD in PT1
500    {
[189]501        pt2_id = boot_next_free_pt2[vspace_id];
[238]502        if (pt2_id == max_pt2) 
503        {
[189]504            boot_puts("\n[BOOT ERROR] in boot_add_pte() function\n");
[228]505            boot_puts("the length of the ptab vobj is too small\n");
[189]506            boot_exit();
507        }
[238]508        else 
509        {
510            pt2_pbase = pt1_pbase + PT1_SIZE + PT2_SIZE * pt2_id;
[246]511            ptd = PTE_V | PTE_T | (unsigned int) (pt2_pbase >> 12);
512            boot_physical_write( pt1_pbase + 4 * ix1, ptd);
[189]513            boot_next_free_pt2[vspace_id] = pt2_id + 1;
514        }
515    }
[238]516    else                       // valid PTD: compute PT2 base address
517    {
518        pt2_pbase = ((paddr_t)(ptd & 0x0FFFFFFF)) << 12;
[189]519    }
520
[238]521    // set PTE in PT2 : flags & PPN in two 32 bits words
[246]522    pte_paddr = pt2_pbase + 8 * ix2;
523    boot_physical_write(pte_paddr    , flags);
524    boot_physical_write(pte_paddr + 4, ppn);
[189]525
[246]526    if (verbose)
527    {
528        boot_puts("     / pt1_pbase = ");
529        boot_putl( pt1_pbase );
530        boot_puts(" / ptd = ");
531        boot_putl( ptd );
532        boot_puts(" / pt2_pbase = ");
533        boot_putl( pt2_pbase );
534        boot_puts(" / pte_paddr = ");
535        boot_putl( pte_paddr );
536        boot_puts(" / ppn = ");
537        boot_putx( ppn );
538        boot_puts("/\n");
539    }
[236]540
[238]541}   // end boot_add_pte()
[228]542
543
[189]544/////////////////////////////////////////////////////////////////////
545// This function build the page table for a given vspace.
546// The physical base addresses for all vsegs (global and private)
[238]547// must have been previously computed and stored in the mapping.
[189]548// It initializes the MWMR channels.
549/////////////////////////////////////////////////////////////////////
[238]550void boot_vspace_pt_build(unsigned int vspace_id) 
551{
[228]552    unsigned int vseg_id;
553    unsigned int npages;
554    unsigned int ppn;
555    unsigned int vpn;
556    unsigned int flags;
557    unsigned int page_id;
[238]558    unsigned int verbose = 0;   // can be used to activate trace in add_pte()
[189]559
[228]560    mapping_header_t * header = (mapping_header_t *) & seg_mapping_base;
561    mapping_vspace_t * vspace = boot_get_vspace_base(header);
[238]562    mapping_vseg_t   * vseg   = boot_get_vseg_base(header);
[228]563
[189]564    // private segments
[228]565    for (vseg_id = vspace[vspace_id].vseg_offset;
[238]566         vseg_id < (vspace[vspace_id].vseg_offset + vspace[vspace_id].vsegs);
567         vseg_id++) 
568    {
[228]569        vpn = vseg[vseg_id].vbase >> 12;
[246]570        ppn = (unsigned int) (vseg[vseg_id].pbase >> 12);
571
[228]572        npages = vseg[vseg_id].length >> 12;
[238]573        if ((vseg[vseg_id].length & 0xFFF) != 0) npages++; 
[189]574
575        flags = PTE_V;
[246]576        if (vseg[vseg_id].mode & C_MODE_MASK) flags = flags | PTE_C;
577        if (vseg[vseg_id].mode & X_MODE_MASK) flags = flags | PTE_X;
578        if (vseg[vseg_id].mode & W_MODE_MASK) flags = flags | PTE_W;
579        if (vseg[vseg_id].mode & U_MODE_MASK) flags = flags | PTE_U;
[189]580
581#if BOOT_DEBUG_PT
[228]582        boot_puts(vseg[vseg_id].name);
583        boot_puts(" : flags = ");
584        boot_putx(flags);
585        boot_puts(" / npages = ");
586        boot_putd(npages);
587        boot_puts(" / pbase = ");
[238]588        boot_putl(vseg[vseg_id].pbase);
[228]589        boot_puts("\n");
590#endif
[189]591        // loop on 4K pages
[238]592        for (page_id = 0; page_id < npages; page_id++) 
593        {
594            boot_add_pte(vspace_id, vpn, flags, ppn, verbose);
[189]595            vpn++;
596            ppn++;
597        }
598    }
599
600    // global segments
[238]601    for (vseg_id = 0; vseg_id < header->globals; vseg_id++) 
602    {
[228]603        vpn = vseg[vseg_id].vbase >> 12;
[238]604        ppn = (unsigned int)(vseg[vseg_id].pbase >> 12);
[228]605        npages = vseg[vseg_id].length >> 12;
[238]606        if ((vseg[vseg_id].length & 0xFFF) != 0) npages++;
[189]607
608        flags = PTE_V;
[238]609        if (vseg[vseg_id].mode & C_MODE_MASK)  flags = flags | PTE_C;
610        if (vseg[vseg_id].mode & X_MODE_MASK)  flags = flags | PTE_X;
611        if (vseg[vseg_id].mode & W_MODE_MASK)  flags = flags | PTE_W;
612        if (vseg[vseg_id].mode & U_MODE_MASK)  flags = flags | PTE_U;
[189]613
614#if BOOT_DEBUG_PT
[228]615        boot_puts(vseg[vseg_id].name);
[238]616        boot_puts(" : flags = ");
[228]617        boot_putx(flags);
618        boot_puts(" / npages = ");
619        boot_putd(npages);
620        boot_puts(" / pbase = ");
[238]621        boot_putl(vseg[vseg_id].pbase);
[228]622        boot_puts("\n");
623#endif
[189]624        // loop on 4K pages
[238]625        for (page_id = 0; page_id < npages; page_id++) 
626        {
627            boot_add_pte(vspace_id, vpn, flags, ppn, verbose);
[189]628            vpn++;
629            ppn++;
630        }
631    }
[238]632}   // end boot_vspace_pt_build()
[189]633
634
635///////////////////////////////////////////////////////////////////////////
[238]636// Align the value of paddr or vaddr to the required alignement,
637// defined by alignPow2 == L2(alignement).
[189]638///////////////////////////////////////////////////////////////////////////
[238]639paddr_t paddr_align_to(paddr_t paddr, unsigned int alignPow2) 
640{
641    paddr_t mask = (1 << alignPow2) - 1;
642    return ((paddr + mask) & ~mask);
643}
644
645unsigned int vaddr_align_to(unsigned int vaddr, unsigned int alignPow2) 
646{
[228]647    unsigned int mask = (1 << alignPow2) - 1;
[238]648    return ((vaddr + mask) & ~mask);
[189]649}
650
651///////////////////////////////////////////////////////////////////////////
[238]652// This function computes the physical base address for a vseg
[189]653// as specified in the mapping info data structure.
654// It updates the pbase and the length fields of the vseg.
655// It updates the pbase and vbase fields of all vobjs in the vseg.
656// It updates the next_base field of the pseg, and checks overflow.
657// It updates the boot_ptabs_paddr[] and boot_ptabs_vaddr[] arrays.
658// It is a global vseg if vspace_id = (-1).
659///////////////////////////////////////////////////////////////////////////
[238]660void boot_vseg_map(mapping_vseg_t * vseg, unsigned int vspace_id) 
661{
[228]662    unsigned int vobj_id;
663    unsigned int cur_vaddr;
[238]664    paddr_t      cur_paddr;
665    unsigned int offset;
666
[228]667    mapping_header_t * header = (mapping_header_t *) & seg_mapping_base;
[238]668    mapping_vobj_t   * vobj   = boot_get_vobj_base(header);
[228]669
[189]670    // get physical segment pointer
[238]671    mapping_pseg_t* pseg = boot_pseg_get(vseg->psegid);
[189]672
673    // compute vseg physical base address
[238]674    if (vseg->ident != 0)                   // identity mapping required
675    {
[228]676        vseg->pbase = vseg->vbase;
[189]677    }
[238]678    else                                   // unconstrained mapping
679    {
[189]680        vseg->pbase = pseg->next_base;
681
682        // test alignment constraint
[238]683        if (vobj[vseg->vobj_offset].align) 
684        {
685            vseg->pbase = paddr_align_to(vseg->pbase, vobj[vseg->vobj_offset].align);
[189]686        }
687    }
[228]688
[189]689    // loop on vobjs contained in vseg to :
690    // (1) computes the length of the vseg,
[230]691    // (2) initialize the vaddr and paddr fields of all vobjs,
692    // (3) initialize the page table pointers arrays
[189]693
694    cur_vaddr = vseg->vbase;
695    cur_paddr = vseg->pbase;
696
[238]697    for (vobj_id = vseg->vobj_offset; 
698         vobj_id < (vseg->vobj_offset + vseg->vobjs); vobj_id++) 
699    {
700        if (vobj[vobj_id].align) 
701        {
702            cur_paddr = paddr_align_to(cur_paddr, vobj[vobj_id].align);
703            cur_vaddr = vaddr_align_to(cur_vaddr, vobj[vobj_id].align);
[189]704        }
[228]705        // set vaddr/paddr for current vobj
706        vobj[vobj_id].vaddr = cur_vaddr;
707        vobj[vobj_id].paddr = cur_paddr;
[230]708       
[246]709        // initialize boot_ptabs_vaddr[] & boot_ptabs-paddr[] if PTAB
[238]710        if (vobj[vobj_id].type == VOBJ_TYPE_PTAB) 
711        {
712            if (vspace_id == ((unsigned int) -1))    // global vseg
713            {
[228]714                boot_puts("\n[BOOT ERROR] in boot_vseg_map() function: ");
715                boot_puts("a PTAB vobj cannot be global");
[189]716                boot_exit();
717            }
[238]718            // we need at least one PT2
719            if (vobj[vobj_id].length < (PT1_SIZE + PT2_SIZE)) 
720            {
[228]721                boot_puts("\n[BOOT ERROR] in boot_vseg_map() function, ");
[189]722                boot_puts("PTAB too small, minumum size is: ");
[228]723                boot_putx(PT1_SIZE + PT2_SIZE);
[189]724                boot_exit();
725            }
726            // register both physical and virtual page table address
[238]727            boot_ptabs_vaddr[vspace_id] = vobj[vobj_id].vaddr;
728            boot_ptabs_paddr[vspace_id] = vobj[vobj_id].paddr;
[246]729           
[238]730            // reset all valid bits in PT1
731            for ( offset = 0 ; offset < 8192 ; offset = offset + 4)
732            {
[246]733                boot_physical_write(cur_paddr + offset, 0);
[238]734            }
735
736            // computing the number of second level pages
[189]737            boot_max_pt2[vspace_id] = (vobj[vobj_id].length - PT1_SIZE) / PT2_SIZE;
738        }
[238]739
[189]740        // set next vaddr/paddr
[238]741        cur_vaddr = cur_vaddr + vobj[vobj_id].length;
742        cur_paddr = cur_paddr + vobj[vobj_id].length;
[189]743    } // end for vobjs
[228]744
[189]745    //set the vseg length
[238]746    vseg->length = vaddr_align_to((unsigned int)(cur_paddr - vseg->pbase), 12);
[189]747
748    // checking pseg overflow
[228]749    if ((vseg->pbase < pseg->base) ||
[238]750        ((vseg->pbase + vseg->length) > (pseg->base + pseg->length))) 
751    {
[189]752        boot_puts("\n[BOOT ERROR] in boot_vseg_map() function\n");
753        boot_puts("impossible mapping for virtual segment: ");
[228]754        boot_puts(vseg->name);
755        boot_puts("\n");
[189]756        boot_puts("vseg pbase = ");
[238]757        boot_putl(vseg->pbase);
[228]758        boot_puts("\n");
[189]759        boot_puts("vseg length = ");
[228]760        boot_putx(vseg->length);
761        boot_puts("\n");
[189]762        boot_puts("pseg pbase = ");
[238]763        boot_putl(pseg->base);
[228]764        boot_puts("\n");
[189]765        boot_puts("pseg length = ");
[238]766        boot_putl(pseg->length);
[228]767        boot_puts("\n");
[189]768        boot_exit();
769    }
770
771#if BOOT_DEBUG_PT
[228]772    boot_puts(vseg->name);
773    boot_puts(" : len = ");
774    boot_putx(vseg->length);
775    boot_puts(" / vbase = ");
776    boot_putx(vseg->vbase);
777    boot_puts(" / pbase = ");
[238]778    boot_putl(vseg->pbase);
[228]779    boot_puts("\n");
780#endif
[189]781
[238]782    // set the next_base field in pseg when it's a RAM
783    if ( pseg->type == PSEG_TYPE_RAM ) 
784    {
[210]785        pseg->next_base = vseg->pbase + vseg->length;
[228]786    }
[238]787}    // end boot_vseg_map()
[210]788
[189]789/////////////////////////////////////////////////////////////////////
790// This function checks consistence beween the  mapping_info data
791// structure (soft), and the giet_config file (hard).
792/////////////////////////////////////////////////////////////////////
[238]793void boot_check_mapping() 
794{
[228]795    mapping_header_t * header = (mapping_header_t *) & seg_mapping_base;
796    mapping_cluster_t * cluster = boot_get_cluster_base(header);
797    mapping_periph_t * periph = boot_get_periph_base(header);
[189]798
799    // checking mapping availability
[238]800    if (header->signature != IN_MAPPING_SIGNATURE) 
801    {
[189]802        boot_puts("\n[BOOT ERROR] Illegal mapping signature: ");
[204]803        boot_putx(header->signature);
[189]804        boot_puts("\n");
805        boot_exit();
806    }
[203]807    // checking number of clusters
[238]808    if (header->clusters != NB_CLUSTERS) 
809    {
[189]810        boot_puts("\n[BOOT ERROR] Incoherent NB_CLUSTERS");
811        boot_puts("\n             - In giet_config,  value = ");
[228]812        boot_putd(NB_CLUSTERS);
[189]813        boot_puts("\n             - In mapping_info, value = ");
[228]814        boot_putd(header->clusters);
[189]815        boot_puts("\n");
816        boot_exit();
817    }
[199]818    // checking number of virtual spaces
[238]819    if (header->vspaces > GIET_NB_VSPACE_MAX) 
820    {
[199]821        boot_puts("\n[BOOT ERROR] : number of vspaces > GIET_NB_VSPACE_MAX\n");
822        boot_puts("\n");
823        boot_exit();
824    }
[203]825    // checking hardware
[199]826    unsigned int periph_id;
827    unsigned int cluster_id;
828    unsigned int tty_found = 0;
829    unsigned int nic_found = 0;
[238]830    for (cluster_id = 0; cluster_id < NB_CLUSTERS; cluster_id++) 
831    {
[199]832        // NB_PROCS_MAX
[238]833        if (cluster[cluster_id].procs > NB_PROCS_MAX) 
834        {
[228]835            boot_puts("\n[BOOT ERROR] too many processors in cluster ");
836            boot_putd(cluster_id);
[199]837            boot_puts(" : procs = ");
[228]838            boot_putd(cluster[cluster_id].procs);
[189]839            boot_puts("\n");
840            boot_exit();
841        }
842
[228]843        for (periph_id = cluster[cluster_id].periph_offset;
844                periph_id < cluster[cluster_id].periph_offset + cluster[cluster_id].periphs;
[238]845                periph_id++) 
846        {
847            // NB_TTY_CHANNELS
848            if (periph[periph_id].type == PERIPH_TYPE_TTY) 
849            {
850                if (tty_found) 
851                {
[199]852                    boot_puts("\n[BOOT ERROR] TTY component should not be replicated\n");
853                    boot_exit();
854                }
[238]855                if (periph[periph_id].channels > NB_TTY_CHANNELS) 
856                {
857                    boot_puts("\n[BOOT ERROR] Wrong NB_TTY_CHANNELS in cluster ");
[228]858                    boot_putd(cluster_id);
[199]859                    boot_puts(" : ttys = ");
[228]860                    boot_putd(periph[periph_id].channels);
[199]861                    boot_puts("\n");
862                    boot_exit();
863                }
864                tty_found = 1;
865            }
[238]866            // NB_NIC_CHANNELS
867            if (periph[periph_id].type == PERIPH_TYPE_NIC) 
868            {
869                if (nic_found) 
870                {
[199]871                    boot_puts("\n[BOOT ERROR] NIC component should not be replicated\n");
872                    boot_exit();
873                }
[238]874                if (periph[periph_id].channels != NB_NIC_CHANNELS) 
875                {
876                    boot_puts("\n[BOOT ERROR] Wrong NB_NIC_CHANNELS in cluster ");
[228]877                    boot_putd(cluster_id);
[199]878                    boot_puts(" : nics = ");
[228]879                    boot_putd(periph[periph_id].channels);
[199]880                    boot_puts("\n");
881                    boot_exit();
882                }
883                nic_found = 1;
884            }
885            // NB_TIMERS
[238]886            if (periph[periph_id].type == PERIPH_TYPE_TIM) 
887            {
888                if (periph[periph_id].channels > NB_TIM_CHANNELS) 
889                {
[199]890                    boot_puts("\n[BOOT ERROR] Too much user timers in cluster ");
[228]891                    boot_putd(cluster_id);
[199]892                    boot_puts(" : timers = ");
[228]893                    boot_putd(periph[periph_id].channels);
[199]894                    boot_puts("\n");
895                    boot_exit();
896                }
897            }
898            // NB_DMAS
[238]899            if (periph[periph_id].type == PERIPH_TYPE_DMA) 
900            {
901                if (periph[periph_id].channels != NB_DMA_CHANNELS) 
902                {
[199]903                    boot_puts("\n[BOOT ERROR] Too much DMA channels in cluster ");
[228]904                    boot_putd(cluster_id);
[199]905                    boot_puts(" : channels = ");
[228]906                    boot_putd(periph[periph_id].channels);
[238]907                    boot_puts(" - NB_DMA_CHANNELS : ");
908                    boot_putd(NB_DMA_CHANNELS);
[199]909                    boot_puts("\n");
910                    boot_exit();
911                }
912            }
913        } // end for periphs
914    } // end for clusters
[189]915} // end boot_check_mapping()
916
917/////////////////////////////////////////////////////////////////////
918// This function initialises the physical pages table allocators
919// for all psegs (i.e. next_base field of the pseg).
920/////////////////////////////////////////////////////////////////////
[238]921void boot_psegs_init() 
922{
923    mapping_header_t* header   = (mapping_header_t *) &seg_mapping_base;
924    mapping_cluster_t* cluster = boot_get_cluster_base(header);
925    mapping_pseg_t* pseg       = boot_get_pseg_base(header);
[189]926
927    unsigned int cluster_id;
928    unsigned int pseg_id;
929
930#if BOOT_DEBUG_PT
[238]931boot_puts ("\n[BOOT DEBUG] ****** psegs allocators initialisation ******\n");
[189]932#endif
933
[238]934    for (cluster_id = 0; cluster_id < header->clusters; cluster_id++) 
935    {
936        if (cluster[cluster_id].procs > NB_PROCS_MAX) 
937        {
[189]938            boot_puts("\n[BOOT ERROR] The number of processors in cluster ");
[228]939            boot_putd(cluster_id);
[189]940            boot_puts(" is larger than NB_PROCS_MAX \n");
941            boot_exit();
942        }
943
[228]944        for (pseg_id = cluster[cluster_id].pseg_offset;
945                pseg_id < cluster[cluster_id].pseg_offset + cluster[cluster_id].psegs;
[238]946                pseg_id++) 
947        {
948            pseg[pseg_id].next_base = pseg[pseg_id].base;
[189]949
950#if BOOT_DEBUG_PT
[238]951boot_puts("cluster ");
952boot_putd(cluster_id);
953boot_puts(" / pseg ");
954boot_puts(pseg[pseg_id].name);
955boot_puts(" : next_base = ");
956boot_putl(pseg[pseg_id].next_base);
957boot_puts("\n");
[189]958#endif
959        }
960    }
[236]961} // end boot_psegs_init()
[189]962
963/////////////////////////////////////////////////////////////////////
964// This function builds the page tables for all virtual spaces
[238]965// defined in the mapping_info data structure, in three steps:
966// - step 1 : It computes the physical base address for global vsegs
967//            and for all associated vobjs.
968// - step 2 : It computes the physical base address for all private
969//            vsegs and all vobjs in each virtual space.
970// - step 3 : It actually fill the page table for each vspace.
[189]971/////////////////////////////////////////////////////////////////////
[238]972void boot_pt_init() 
973{
[228]974    mapping_header_t * header = (mapping_header_t *) &seg_mapping_base;
975    mapping_vspace_t * vspace = boot_get_vspace_base(header);
[238]976    mapping_vseg_t   * vseg   = boot_get_vseg_base(header);
[189]977
[228]978    unsigned int vspace_id;
979    unsigned int vseg_id;
[189]980
981#if BOOT_DEBUG_PT
[238]982boot_puts("\n[BOOT DEBUG] ****** mapping global vsegs ******\n");
[189]983#endif
[228]984
[238]985    // step 1 : loop on virtual spaces to map global vsegs
986    for (vseg_id = 0; vseg_id < header->globals; vseg_id++) 
987    {
[228]988        boot_vseg_map(&vseg[vseg_id], ((unsigned int) (-1)));
[189]989    }
990
991    // step 2 : loop on virtual vspaces to map private vsegs
[238]992    for (vspace_id = 0; vspace_id < header->vspaces; vspace_id++) 
993    {
[189]994
995#if BOOT_DEBUG_PT
[238]996boot_puts("\n[BOOT DEBUG] ****** mapping private vsegs in vspace ");
997boot_puts(vspace[vspace_id].name);
998boot_puts(" ******\n");
[189]999#endif
[228]1000
1001        for (vseg_id = vspace[vspace_id].vseg_offset;
[246]1002             vseg_id < (vspace[vspace_id].vseg_offset + vspace[vspace_id].vsegs);
1003             vseg_id++) 
[238]1004        {
[228]1005            boot_vseg_map(&vseg[vseg_id], vspace_id);
[189]1006        }
[228]1007    }
[189]1008
1009    // step 3 : loop on the vspaces to build the page tables
[238]1010    for (vspace_id = 0; vspace_id < header->vspaces; vspace_id++) 
1011    {
[189]1012#if BOOT_DEBUG_PT
[238]1013boot_puts("\n[BOOT DEBUG] ****** building page table for vspace ");
1014boot_puts(vspace[vspace_id].name);
1015boot_puts(" ******\n");
[189]1016#endif
[228]1017        boot_vspace_pt_build(vspace_id);
1018
[189]1019#if BOOT_DEBUG_PT
[238]1020boot_puts("\n>>> page table physical address = ");
1021boot_putl(boot_ptabs_paddr[vspace_id]);
1022boot_puts(", number of PT2 = ");
1023boot_putd((unsigned int) boot_max_pt2[vspace_id]);
1024boot_puts("\n");
[189]1025#endif
[228]1026    }
[189]1027} // end boot_pt_init()
1028
1029///////////////////////////////////////////////////////////////////////////////
1030// This function initializes all private vobjs defined in the vspaces,
1031// such as mwmr channels, barriers and locks, because these vobjs
[228]1032// are not known, and not initialized by the compiler.
[238]1033// Warning : The MMU is supposed to be activated...
[189]1034///////////////////////////////////////////////////////////////////////////////
[238]1035void boot_vobjs_init() 
1036{
1037    mapping_header_t* header = (mapping_header_t *) & seg_mapping_base;
1038    mapping_vspace_t* vspace = boot_get_vspace_base(header);
1039    mapping_vobj_t* vobj     = boot_get_vobj_base(header);
[189]1040
[228]1041    unsigned int vspace_id;
1042    unsigned int vobj_id;
[189]1043
[238]1044    // loop on the vspaces
1045    for (vspace_id = 0; vspace_id < header->vspaces; vspace_id++) 
1046    {
[189]1047
1048#if BOOT_DEBUG_VOBJS
[238]1049boot_puts("\n[BOOT DEBUG] ****** vobjs initialisation in vspace ");
1050boot_puts(vspace[vspace_id].name);
1051boot_puts(" ******\n");
[189]1052#endif
1053
1054        unsigned int ptab_found = 0;
1055
1056        // loop on the vobjs
[228]1057        for (vobj_id = vspace[vspace_id].vobj_offset;
[238]1058             vobj_id < (vspace[vspace_id].vobj_offset + vspace[vspace_id].vobjs);
1059             vobj_id++) 
1060        {
1061            switch (vobj[vobj_id].type) 
1062            {
[228]1063                case VOBJ_TYPE_MWMR:    // storage capacity is (vobj.length/4 - 5) words
1064                {
[238]1065                    mwmr_channel_t* mwmr = (mwmr_channel_t *) (vobj[vobj_id].vaddr);
[228]1066                    mwmr->ptw = 0;
1067                    mwmr->ptr = 0;
1068                    mwmr->sts = 0;
[189]1069                    mwmr->width = vobj[vobj_id].init;
[228]1070                    mwmr->depth = (vobj[vobj_id].length >> 2) - 6;
1071                    mwmr->lock = 0;
[189]1072#if BOOT_DEBUG_VOBJS
[238]1073boot_puts("MWMR    : ");
1074boot_puts(vobj[vobj_id].name);
1075boot_puts(" / depth = ");
1076boot_putd(mwmr->depth);
1077boot_puts(" / width = ");
1078boot_putd(mwmr->width);
1079boot_puts("\n");
[189]1080#endif
1081                    break;
1082                }
[228]1083                case VOBJ_TYPE_ELF:    // initialisation done by the loader
[189]1084                {
1085#if BOOT_DEBUG_VOBJS
[238]1086boot_puts("ELF     : ");
1087boot_puts(vobj[vobj_id].name);
1088boot_puts(" / length = ");
1089boot_putx(vobj[vobj_id].length);
1090boot_puts("\n");
[189]1091#endif
1092                    break;
1093                }
[228]1094                case VOBJ_TYPE_BLOB:    // initialisation done by the loader
[189]1095                {
1096#if BOOT_DEBUG_VOBJS
[238]1097boot_puts("BLOB     : ");
1098boot_puts(vobj[vobj_id].name);
1099boot_puts(" / length = ");
1100boot_putx(vobj[vobj_id].length);
1101boot_puts("\n");
[189]1102#endif
1103                    break;
1104                }
[228]1105                case VOBJ_TYPE_BARRIER:    // init is the number of participants
[189]1106                {
[238]1107                    giet_barrier_t* barrier = (giet_barrier_t *) (vobj[vobj_id].vaddr);
[228]1108                    barrier->count = vobj[vobj_id].init;
1109                    barrier->init = vobj[vobj_id].init;
[189]1110#if BOOT_DEBUG_VOBJS
[238]1111boot_puts("BARRIER : ");
1112boot_puts(vobj[vobj_id].name);
1113boot_puts(" / init_value = ");
1114boot_putd(barrier->init);
1115boot_puts("\n");
[189]1116#endif
1117                    break;
1118                }
[238]1119                case VOBJ_TYPE_LOCK:    // init value is "not taken"
[189]1120                {
[238]1121                    unsigned int* lock = (unsigned int *) (vobj[vobj_id].vaddr);
[189]1122                    *lock = 0;
1123#if BOOT_DEBUG_VOBJS
[238]1124boot_puts("LOCK    : ");
1125boot_puts(vobj[vobj_id].name);
1126boot_puts("\n");
[189]1127#endif
1128                    break;
1129                }
[228]1130                case VOBJ_TYPE_BUFFER:    // nothing to initialise
[189]1131                {
1132#if BOOT_DEBUG_VOBJS
[238]1133boot_puts("BUFFER  : ");
1134boot_puts(vobj[vobj_id].name);
1135boot_puts(" / paddr = ");
[246]1136boot_putl(vobj[vobj_id].paddr);
[238]1137boot_puts(" / length = ");
1138boot_putx(vobj[vobj_id].length);
1139boot_puts("\n");
[189]1140#endif
1141                    break;
1142                }
[228]1143                case VOBJ_TYPE_MEMSPACE:
[189]1144                {
[238]1145                    giet_memspace_t* memspace = (giet_memspace_t *) vobj[vobj_id].vaddr;
[228]1146                    memspace->buffer = (void *) vobj[vobj_id].vaddr + 8;
1147                    memspace->size = vobj[vobj_id].length - 8;
1148#if BOOT_DEBUG_VOBJS
[238]1149boot_puts("MEMSPACE  : ");
1150boot_puts(vobj[vobj_id].name);
1151boot_puts(" / vaddr = ");
1152boot_putx(vobj[vobj_id].vaddr);
1153boot_puts(" / length = ");
1154boot_putx(vobj[vobj_id].length);
1155boot_puts(" / buffer = ");
1156boot_putx((unsigned int)memspace->buffer);
1157boot_puts(" / size = ");
1158boot_putx(memspace->size);
1159boot_puts("\n");
[228]1160#endif
1161                    break;
1162                }
[230]1163                case VOBJ_TYPE_PTAB:    // nothing to initialize
[228]1164                {
[189]1165                    ptab_found = 1;
1166#if BOOT_DEBUG_VOBJS
[238]1167boot_puts("PTAB    : ");
1168boot_puts(vobj[vobj_id].name);
1169boot_puts(" / length = ");
1170boot_putx(vobj[vobj_id].length);
1171boot_puts("\n");
[189]1172#endif
1173                    break;
1174                }
[228]1175                case VOBJ_TYPE_CONST:
1176                {
[238]1177                    unsigned int* addr = (unsigned int *) vobj[vobj_id].vaddr;
[230]1178                    *addr = vobj[vobj_id].init;
[228]1179#if BOOT_DEBUG_VOBJS
[238]1180boot_puts("CONST   : ");
1181boot_puts(vobj[vobj_id].name);
1182boot_puts(" / Paddr :");
[246]1183boot_putl(vobj[vobj_id].paddr);
[238]1184boot_puts(" / init = ");
1185boot_putx(*addr);
1186boot_puts("\n");
[228]1187#endif
1188                    break;
1189                }
[189]1190                default:
1191                {
[238]1192                    boot_puts("\n[BOOT ERROR] illegal vobj type: ");
[228]1193                    boot_putd(vobj[vobj_id].type);
[230]1194                    boot_puts("\n");
[189]1195                    boot_exit();
1196                }
[228]1197            }            // end switch type
1198        }            // end loop on vobjs
[238]1199        if (ptab_found == 0) 
1200        {
1201            boot_puts("\n[BOOT ERROR] Missing PTAB for vspace ");
[228]1202            boot_putd(vspace_id);
[189]1203            boot_exit();
1204        }
1205    } // end loop on vspaces
1206} // end boot_vobjs_init()
1207
[238]1208////////////////////////////////////////////////////////////////////////////////
1209// This function initializes one MWMR controller channel.
1210// - coproc_pbase  : physical base address of the Coproc configuration segment
1211// - channel_pbase : physical base address of the MWMR channel segment
1212// Warning : the channel physical base address should be on 32 bits, as the
1213// MWMR controller configuration registers are 32 bits.
1214// TODO : Introduce a MWMR_CONFIG_PADDR_EXT register in the MWMR coprocessor
1215//        To support addresses > 32 bits and remove this limitation...
1216///////////////////////////////////////////////////////////////////////////////
1217void mwmr_hw_init(paddr_t                coproc_pbase, 
1218                  enum mwmrPortDirection way,
1219                  unsigned int           no, 
1220                  paddr_t                channel_pbase) 
1221{
1222    if ( (channel_pbase>>32) != 0 )
1223    {
1224        boot_puts("\n[BOOT ERROR] MWMR controller does not support address > 32 bits\n");
1225        boot_exit();
1226    }
[228]1227
[238]1228    unsigned int lsb = (unsigned int)channel_pbase;
1229//  unsigned int msb = (unsigned int)(channel_pbase>>32);
[228]1230
[238]1231    unsigned int depth = boot_physical_read( channel_pbase + 16 );
1232    unsigned int width = boot_physical_read( channel_pbase + 20 );
1233
1234    boot_physical_write( coproc_pbase + MWMR_CONFIG_FIFO_WAY*4, way );
1235    boot_physical_write( coproc_pbase + MWMR_CONFIG_FIFO_NO*4, no );
1236    boot_physical_write( coproc_pbase + MWMR_CONFIG_WIDTH*4, width);
1237    boot_physical_write( coproc_pbase + MWMR_CONFIG_DEPTH*4, depth);
1238    boot_physical_write( coproc_pbase + MWMR_CONFIG_STATUS_ADDR*4, lsb);
1239    boot_physical_write( coproc_pbase + MWMR_CONFIG_BUFFER_ADDR*4, lsb + 24 );
1240//  boot_physical_write( coproc_pbase + MWMR_CONFIG_PADDR_EXT*4, msb);
1241    boot_physical_write( coproc_pbase + MWMR_CONFIG_RUNNING*4, 1 );
[200]1242}
1243
[189]1244////////////////////////////////////////////////////////////////////////////////
1245// This function intializes the periherals and coprocessors, as specified
[203]1246// in the mapping_info file.
[189]1247////////////////////////////////////////////////////////////////////////////////
[238]1248void boot_peripherals_init() 
1249{
[228]1250    mapping_header_t * header = (mapping_header_t *) & seg_mapping_base;
1251    mapping_cluster_t * cluster = boot_get_cluster_base(header);
1252    mapping_periph_t * periph = boot_get_periph_base(header);
1253    mapping_pseg_t * pseg = boot_get_pseg_base(header);
1254    mapping_vobj_t * vobj = boot_get_vobj_base(header);
1255    mapping_vspace_t * vspace = boot_get_vspace_base(header);
1256    mapping_coproc_t * coproc = boot_get_coproc_base(header);
1257    mapping_cp_port_t * cp_port = boot_get_cp_port_base(header);
[189]1258
[228]1259    unsigned int cluster_id;
1260    unsigned int periph_id;
1261    unsigned int coproc_id;
1262    unsigned int cp_port_id;
1263    unsigned int channel_id;
[189]1264
[238]1265    for (cluster_id = 0; cluster_id < header->clusters; cluster_id++) 
1266    {
[189]1267
1268#if BOOT_DEBUG_PERI
[238]1269boot_puts("\n[BOOT DEBUG] ****** peripherals initialisation in cluster ");
1270boot_putd(cluster_id);
1271boot_puts(" ******\n");
[189]1272#endif
1273
[228]1274        for (periph_id = cluster[cluster_id].periph_offset;
[238]1275             periph_id < cluster[cluster_id].periph_offset +
1276             cluster[cluster_id].periphs; periph_id++) 
1277        {
[228]1278            unsigned int type = periph[periph_id].type;
1279            unsigned int channels = periph[periph_id].channels;
1280            unsigned int pseg_id = periph[periph_id].psegid;
[189]1281
[238]1282            paddr_t pbase = pseg[pseg_id].base;
[189]1283
1284#if BOOT_DEBUG_PERI
[238]1285boot_puts("- peripheral type : ");
1286boot_putd(type);
1287boot_puts(" / pbase = ");
1288boot_putl(pbase);
1289boot_puts(" / channels = ");
1290boot_putd(channels);
1291boot_puts("\n");
[189]1292#endif
1293
[238]1294            switch (type) 
1295            {
[228]1296                case PERIPH_TYPE_IOC:    // vci_block_device component
[238]1297                {
1298                    paddr_t paddr = pbase + BLOCK_DEVICE_IRQ_ENABLE*4;
1299                    boot_physical_write(paddr, 1);
[189]1300#if BOOT_DEBUG_PERI
[238]1301boot_puts("- IOC initialised\n");
[189]1302#endif
[238]1303                }
1304                break;
[228]1305                case PERIPH_TYPE_DMA:    // vci_multi_dma component
[238]1306                    for (channel_id = 0; channel_id < channels; channel_id++) 
1307                    {
1308                        paddr_t paddr = pbase + (channel_id*DMA_SPAN + DMA_IRQ_DISABLE) * 4;
1309                        boot_physical_write(paddr, 0);
[218]1310                    }
[189]1311#if BOOT_DEBUG_PERI
[238]1312boot_puts("- DMA initialised\n");
[189]1313#endif
[238]1314                break;
[228]1315                case PERIPH_TYPE_NIC:    // vci_multi_nic component
[238]1316                    for (channel_id = 0; channel_id < channels; channel_id++) 
1317                    {
[218]1318                        // TODO
1319                    }
1320#if BOOT_DEBUG_PERI
[238]1321boot_puts("- NIC initialised\n");
[218]1322#endif
[238]1323                break;
[228]1324                case PERIPH_TYPE_TTY:    // vci_multi_tty component
[218]1325#if BOOT_DEBUG_PERI
[238]1326boot_puts("- TTY initialised\n");
[218]1327#endif
[238]1328                break;
[228]1329                case PERIPH_TYPE_IOB:    // vci_io_bridge component
[238]1330                    if (IOMMU_ACTIVE) 
1331                    {
[218]1332                        // TODO
1333                        // get the iommu page table physical address
1334                        // define IPI address mapping the IOC interrupt
1335                        // set IOMMU page table address
1336                        // pseg_base[IOB_IOMMU_PTPR] = ptab_pbase;   
1337                        // activate IOMMU
1338                        // pseg_base[IOB_IOMMU_ACTIVE] = 1;       
1339                    }
1340#if BOOT_DEBUG_PERI
[238]1341boot_puts("- IOB initialised\n");
[218]1342#endif
[238]1343                break;
1344            }  // end switch periph type
1345        }  // end for periphs
[189]1346
1347#if BOOT_DEBUG_PERI
[238]1348boot_puts("\n[BOOT DEBUG] ****** coprocessors initialisation in cluster ");
1349boot_putd(cluster_id);
1350boot_puts(" ******\n");
[189]1351#endif
1352
[228]1353        for (coproc_id = cluster[cluster_id].coproc_offset;
[238]1354             coproc_id < cluster[cluster_id].coproc_offset +
1355             cluster[cluster_id].coprocs; coproc_id++) 
1356        {
1357            unsigned no_fifo_to = 0;    //FIXME: should the map.xml define the order?
[200]1358            unsigned no_fifo_from = 0;
1359
[238]1360            // Get physical base address for MWMR controler
1361            paddr_t coproc_pbase = pseg[coproc[coproc_id].psegid].base;
1362
[200]1363#if BOOT_DEBUG_PERI
[238]1364boot_puts("- coprocessor name : ");
1365boot_puts(coproc[coproc_id].name);
1366boot_puts(" / nb ports = ");
1367boot_putd((unsigned int) coproc[coproc_id].ports);
1368boot_puts("\n");
[200]1369#endif
1370
[228]1371            for (cp_port_id = coproc[coproc_id].port_offset;
[238]1372                 cp_port_id < coproc[coproc_id].port_offset + coproc[coproc_id].ports;
1373                 cp_port_id++) 
1374            {
[228]1375                unsigned int vspace_id = cp_port[cp_port_id].vspaceid;
[238]1376                unsigned int vobj_id = cp_port[cp_port_id].mwmr_vobjid + 
1377                                          vspace[vspace_id].vobj_offset;
[200]1378
[238]1379                // Get MWMR channel base address
1380                paddr_t channel_pbase = vobj[vobj_id].paddr;
[200]1381
[238]1382                if (cp_port[cp_port_id].direction == PORT_TO_COPROC) 
1383                {
[200]1384#if BOOT_DEBUG_PERI
[238]1385boot_puts("     port direction: PORT_TO_COPROC");
[200]1386#endif
[238]1387                    mwmr_hw_init(coproc_pbase, 
1388                                 PORT_TO_COPROC, 
1389                                 no_fifo_to, 
1390                                 channel_pbase);
[200]1391                    no_fifo_to++;
1392                }
[238]1393                else 
1394                {
[200]1395#if BOOT_DEBUG_PERI
[238]1396boot_puts("     port direction: PORT_FROM_COPROC");
[200]1397#endif
[238]1398                    mwmr_hw_init(coproc_pbase, 
1399                                 PORT_FROM_COPROC, 
1400                                 no_fifo_from, 
1401                                 channel_pbase);
[200]1402                    no_fifo_from++;
1403                }
1404#if BOOT_DEBUG_PERI
[238]1405boot_puts(", with mwmr: ");
1406boot_puts(vobj[vobj_id].name);
1407boot_puts(" of vspace: ");
1408boot_puts(vspace[vspace_id].name);
[200]1409#endif
[238]1410            } // end for cp_ports
[189]1411        } // end for coprocs
1412    } // end for clusters
1413} // end boot_peripherals_init()
1414
[238]1415///////////////////////////////////////////////////////////////////////////////
1416// This function returns in the vbase and length buffers the virtual base
1417// address and the length of the  segment allocated to the schedulers array
1418// in the cluster defined by the clusterid argument.
1419///////////////////////////////////////////////////////////////////////////////
1420void boot_get_sched_vaddr( unsigned int  cluster_id,
1421                           unsigned int* vbase, 
1422                           unsigned int* length )
1423{
1424    mapping_header_t* header = (mapping_header_t *) & seg_mapping_base;
1425    mapping_vobj_t*   vobj   = boot_get_vobj_base(header);
1426    mapping_vseg_t*   vseg   = boot_get_vseg_base(header);
1427    mapping_pseg_t*   pseg   = boot_get_pseg_base(header);
[189]1428
[238]1429    unsigned int vseg_id;
1430    unsigned int found = 0;
1431
1432    for ( vseg_id = 0 ; (vseg_id < header->vsegs) && (found == 0) ; vseg_id++ )
1433    {
1434        if ( (vobj[vseg[vseg_id].vobj_offset].type == VOBJ_TYPE_SCHED) && 
1435             (pseg[vseg[vseg_id].psegid].cluster == cluster_id ) )
1436        {
1437            *vbase  = vseg[vseg_id].vbase;
1438            *length = vobj[vseg[vseg_id].vobj_offset].length;
1439            found = 1;
1440        }
1441    }
1442    if ( found == 0 )
1443    {
1444        boot_puts("\n[BOOT ERROR] No vobj of type SCHED in cluster ");
1445        boot_putd(cluster_id);
1446        boot_puts("\n");
1447        boot_exit();
1448    }
1449} // end boot_get_sched_vaddr()
1450
[189]1451///////////////////////////////////////////////////////////////////////////////
1452// This function initialises all processors schedulers.
1453// This is done by processor 0, and the MMU must be activated.
[238]1454// It initialises the boot_chedulers[gpid] pointers array.
[189]1455// Finally, it scan all tasks in all vspaces to initialise the tasks contexts,
1456// as specified in the mapping_info data structure.
1457// For each task, a TTY channel, a TIMER channel, a FBDMA channel, and a NIC
[238]1458// channel are allocated if required.
[189]1459///////////////////////////////////////////////////////////////////////////////
[238]1460void boot_schedulers_init() 
1461{
1462    mapping_header_t*  header  = (mapping_header_t *) & seg_mapping_base;
1463    mapping_cluster_t* cluster = boot_get_cluster_base(header);
1464    mapping_vspace_t*  vspace  = boot_get_vspace_base(header);
1465    mapping_task_t*    task    = boot_get_task_base(header);
1466    mapping_vobj_t*    vobj    = boot_get_vobj_base(header);
1467    mapping_proc_t*    proc    = boot_get_proc_base(header);
1468    mapping_irq_t*     irq     = boot_get_irq_base(header);
[189]1469
[238]1470    unsigned int cluster_id;    // cluster index in mapping_info
1471    unsigned int proc_id;       // processor index in mapping_info
1472    unsigned int irq_id;        // irq index in mapping_info
1473    unsigned int vspace_id;     // vspace index in mapping_info
1474    unsigned int task_id;       // task index in mapping_info
1475
1476    unsigned int alloc_tty_channel = 1;            // TTY channel allocator
1477    unsigned int alloc_nic_channel = 0;            // NIC channel allocator
1478    unsigned int alloc_cma_channel = 0;            // CMA channel allocator
1479    unsigned int alloc_ioc_channel = 0;            // IOC channel allocator
[228]1480    unsigned int alloc_dma_channel[NB_CLUSTERS];   // DMA channel allocators
[238]1481    unsigned int alloc_tim_channel[NB_CLUSTERS];   // user TIMER allocators
[189]1482
[238]1483    /////////////////////////////////////////////////////////////////////////
1484    // Step 1 : loop on the clusters and on the processors
1485    //          to initialize the schedulers[] array of pointers and
1486    //          the interrupt vectors.
1487    // Implementation note:
1488    // We need to use both proc_id to scan the mapping info structure,
1489    // and lpid to access the schedulers array.
1490    // - the boot_schedulers[] array of pointers can contain "holes", because
1491    //   it is indexed by the global pid = cluster_id*NB_PROCS_MAX + ltid
1492    // - the mapping info array of processors is contiguous, it is indexed
1493    //   by proc_id, and use an offset specific in each cluster.
[189]1494
[238]1495    for (cluster_id = 0; cluster_id < header->clusters; cluster_id++) 
1496    {
[189]1497
[238]1498#if BOOT_DEBUG_SCHED
1499boot_puts("\n[BOOT DEBUG] Initialise schedulers in cluster ");
1500boot_putd(cluster_id);
1501boot_puts("\n");
1502#endif
[189]1503
[238]1504        // TTY, NIC, CMA, IOC, TIM and DMA channels allocators
1505        // - TTY[0] is reserved for the kernel
1506        // - In all clusters the first NB_PROCS_MAX timers
1507        //   are reserved for the kernel (context switch)
1508
[228]1509        alloc_dma_channel[cluster_id] = 0;
[238]1510        alloc_tim_channel[cluster_id] = NB_PROCS_MAX;
[228]1511
[238]1512        unsigned int  lpid;          // processor local index in cluster
1513        unsigned int  sched_vbase;   // schedulers segment virtual base address
1514        unsigned int  sched_length;  // schedulers segment length
1515        unsigned int  nprocs;        // number of processors in cluster
[189]1516
[238]1517        nprocs = cluster[cluster_id].procs;
[189]1518
[238]1519        // checking processors number
1520        if ( nprocs > NB_PROCS_MAX )
1521        {
1522            boot_puts("\n[BOOT ERROR] Too much processors in cluster ");
1523            boot_putd(cluster_id);
1524            boot_puts("\n");
1525            boot_exit();
[189]1526        }
[238]1527 
1528        // get scheduler array virtual base address for cluster_id
1529        boot_get_sched_vaddr( cluster_id, &sched_vbase, &sched_length );
[189]1530
[240]1531        // each processor scheduler requires 4 Kbytes
1532        if ( sched_length < (nprocs<<12) ) 
[238]1533        {
1534            boot_puts("\n[BOOT ERROR] Schedulers segment too small in cluster ");
[228]1535            boot_putd(cluster_id);
[189]1536            boot_puts("\n");
1537            boot_exit();
1538        }
1539
[238]1540        for ( proc_id = cluster[cluster_id].proc_offset, lpid = 0 ;
1541              proc_id < cluster[cluster_id].proc_offset + cluster[cluster_id].procs;
1542              proc_id++, lpid++ ) 
1543        {
1544            // set the schedulers pointers array
1545            boot_schedulers[cluster_id * NB_PROCS_MAX + lpid] =
[240]1546               (static_scheduler_t*)( sched_vbase + (lpid<<12) );
[189]1547
1548#if BOOT_DEBUG_SCHED
[238]1549boot_puts("\nProc ");
1550boot_putd(lpid);
1551boot_puts(" : scheduler virtual base address = ");
[240]1552boot_putx( sched_vbase + (lpid<<12) );
[238]1553boot_puts("\n");
[189]1554#endif
[238]1555            // current processor scheduler pointer : psched
[240]1556            static_scheduler_t* psched = (static_scheduler_t*)(sched_vbase+(lpid<<12));
[228]1557
[238]1558            // initialise the "tasks" variable
1559            psched->tasks = 0;
1560
[189]1561            // initialise the interrupt_vector with ISR_DEFAULT
1562            unsigned int slot;
[238]1563            for (slot = 0; slot < 32; slot++) psched->interrupt_vector[slot] = 0;
[189]1564
1565            // scan the IRQs actually allocated to current processor
[228]1566            for (irq_id = proc[proc_id].irq_offset;
[238]1567                 irq_id < proc[proc_id].irq_offset + proc[proc_id].irqs;
1568                 irq_id++) 
1569            {
[228]1570                unsigned int type = irq[irq_id].type;
1571                unsigned int icu_id = irq[irq_id].icuid;
1572                unsigned int isr_id = irq[irq_id].isr;
[189]1573                unsigned int channel = irq[irq_id].channel;
[228]1574                unsigned int value = isr_id | (type << 8) | (channel << 16);
[238]1575                psched->interrupt_vector[icu_id] = value;
[189]1576
1577#if BOOT_DEBUG_SCHED
[238]1578boot_puts("- IRQ : icu = ");
1579boot_putd(icu_id);
1580boot_puts(" / type = ");
1581boot_putd(type);
1582boot_puts(" / isr = ");
1583boot_putd(isr_id);
1584boot_puts(" / channel = ");
1585boot_putd(channel);
1586boot_puts(" => vector_entry = ");
1587boot_putx( value );
1588boot_puts("\n");
[189]1589#endif
1590            }
1591        } // end for procs
1592    } // end for clusters
1593
[238]1594    ///////////////////////////////////////////////////////////////////
[189]1595    // Step 2 : loop on the vspaces and the tasks
1596    //          to initialise the schedulers and the task contexts.
[238]1597    // Implementation note:
1598    // This function initialises the task context for all tasks.
1599    // For each processor, the scheduler virtual base address
1600    // is written in the CP0_SCHED register in reset.S
[189]1601
[238]1602    for (vspace_id = 0; vspace_id < header->vspaces; vspace_id++) 
1603    {
[189]1604
1605#if BOOT_DEBUG_SCHED
[238]1606boot_puts("\n[BOOT DEBUG] Initialise task contexts for vspace ");
1607boot_puts(vspace[vspace_id].name);
1608boot_puts("\n");
[189]1609#endif
1610        // We must set the PTPR depending on the vspace, because the start_vector
1611        // and the stack address are defined in virtual space.
[238]1612        boot_set_mmu_ptpr( (unsigned int)(boot_ptabs_paddr[vspace_id] >> 13) );
[189]1613
[197]1614        // loop on the tasks in vspace (task_id is the global index)
[228]1615        for (task_id = vspace[vspace_id].task_offset;
[238]1616             task_id < (vspace[vspace_id].task_offset + vspace[vspace_id].tasks);
1617             task_id++) 
1618        {
1619            // compute gpid (global processor index) and scheduler base address
1620            unsigned int gpid = task[task_id].clusterid * NB_PROCS_MAX + 
1621                                task[task_id].proclocid;
1622            static_scheduler_t* psched = boot_schedulers[gpid];
1623
[199]1624            // ctx_ra :  the return address is &boot_eret()
[228]1625            unsigned int ctx_ra = (unsigned int) &boot_eret;
[189]1626
[199]1627            // ctx_sr : value required before an eret instruction
[228]1628            unsigned int ctx_sr = 0x0000FF13;
[189]1629
[199]1630            // ctx_ptpr : page table physical base address (shifted by 13 bit)
[238]1631            unsigned int ctx_ptpr = (unsigned int)(boot_ptabs_paddr[vspace_id] >> 13);
[189]1632
[199]1633            // ctx_ptab : page_table virtual base address
[238]1634            unsigned int ctx_ptab = boot_ptabs_vaddr[vspace_id];
[189]1635
[238]1636            // ctx_tty : terminal global index provided by the global allocator
[199]1637            unsigned int ctx_tty = 0xFFFFFFFF;
[238]1638            if (task[task_id].use_tty) 
1639            {
1640                if (alloc_tty_channel >= NB_TTY_CHANNELS) 
1641                {
[189]1642                    boot_puts("\n[BOOT ERROR] TTY index too large for task ");
[228]1643                    boot_puts(task[task_id].name);
[189]1644                    boot_puts(" in vspace ");
[228]1645                    boot_puts(vspace[vspace_id].name);
[189]1646                    boot_puts("\n");
1647                    boot_exit();
1648                }
[199]1649                ctx_tty = alloc_tty_channel;
[189]1650                alloc_tty_channel++;
1651            }
[238]1652            // ctx_nic : NIC channel global index provided by the global allocator
[199]1653            unsigned int ctx_nic = 0xFFFFFFFF;
[238]1654            if (task[task_id].use_nic) 
1655            {
1656                if (alloc_nic_channel >= NB_NIC_CHANNELS) 
1657                {
[189]1658                    boot_puts("\n[BOOT ERROR] NIC channel index too large for task ");
[228]1659                    boot_puts(task[task_id].name);
[189]1660                    boot_puts(" in vspace ");
[228]1661                    boot_puts(vspace[vspace_id].name);
[189]1662                    boot_puts("\n");
1663                    boot_exit();
1664                }
[199]1665                ctx_nic = alloc_nic_channel;
[189]1666                alloc_nic_channel++;
1667            }
[238]1668            // ctx_cma : CMA channel global index provided by the global allocator
1669            unsigned int ctx_cma = 0xFFFFFFFF;
1670            if (task[task_id].use_cma) 
1671            {
1672                if (alloc_cma_channel >= NB_CMA_CHANNELS) 
1673                {
1674                    boot_puts("\n[BOOT ERROR] CMA channel index too large for task ");
1675                    boot_puts(task[task_id].name);
1676                    boot_puts(" in vspace ");
1677                    boot_puts(vspace[vspace_id].name);
1678                    boot_puts("\n");
1679                    boot_exit();
1680                }
1681                ctx_cma = alloc_cma_channel;
1682                alloc_cma_channel++;
1683            }
1684            // ctx_ioc : IOC channel global index provided by the global allocator
1685            unsigned int ctx_ioc = 0xFFFFFFFF;
1686            if (task[task_id].use_ioc) 
1687            {
1688                if (alloc_ioc_channel >= NB_IOC_CHANNELS) 
1689                {
1690                    boot_puts("\n[BOOT ERROR] IOC channel index too large for task ");
1691                    boot_puts(task[task_id].name);
1692                    boot_puts(" in vspace ");
1693                    boot_puts(vspace[vspace_id].name);
1694                    boot_puts("\n");
1695                    boot_exit();
1696                }
1697                ctx_ioc = alloc_ioc_channel;
1698                alloc_ioc_channel++;
1699            }
1700            // ctx_tim : TIMER local channel index provided by the cluster allocator
1701            unsigned int ctx_tim = 0xFFFFFFFF;
1702            if (task[task_id].use_tim) 
1703            {
[189]1704                unsigned int cluster_id = task[task_id].clusterid;
[215]1705
[238]1706                if ( alloc_tim_channel[cluster_id] >= NB_TIM_CHANNELS ) 
1707                {
[189]1708                    boot_puts("\n[BOOT ERROR] local TIMER index too large for task ");
[228]1709                    boot_puts(task[task_id].name);
[189]1710                    boot_puts(" in vspace ");
[228]1711                    boot_puts(vspace[vspace_id].name);
[189]1712                    boot_puts("\n");
1713                    boot_exit();
1714                }
[238]1715
1716                // checking that there is a well defined ISR_TIMER installed
1717                unsigned int found = 0;
1718                for ( irq_id = 0 ; irq_id < 32 ; irq_id++ ) 
1719                {
1720                    unsigned int entry   = psched->interrupt_vector[irq_id];
1721                    unsigned int isr     = entry & 0x000000FF;
1722                    unsigned int channel = entry>>16;
1723                    if ( (isr == ISR_TIMER) && (channel == alloc_tim_channel[cluster_id]) ) 
1724                    {
1725                        found     = 1;
1726                        ctx_tim =  alloc_tim_channel[cluster_id];
1727                        alloc_tim_channel[cluster_id]++;
1728                        break;
[215]1729                    }
1730                }
[238]1731                if (!found) 
1732                {
1733                    boot_puts("\n[BOOT ERROR] No ISR_TIMER installed for task ");
[228]1734                    boot_puts(task[task_id].name);
[215]1735                    boot_puts(" in vspace ");
[228]1736                    boot_puts(vspace[vspace_id].name);
[215]1737                    boot_puts("\n");
1738                    boot_exit();
1739                }
[189]1740            }
[238]1741            // ctx_dma : the local channel index is defined by the cluster allocator 
1742            //           but the ctx_dma value is a global index
[218]1743            unsigned int ctx_dma = 0xFFFFFFFF;
[238]1744            if ( task[task_id].use_dma ) 
1745            {
[189]1746                unsigned int cluster_id = task[task_id].clusterid;
[238]1747
1748                if (alloc_dma_channel[cluster_id] >= NB_DMA_CHANNELS) 
1749                {
[218]1750                    boot_puts("\n[BOOT ERROR] local DMA index too large for task ");
[228]1751                    boot_puts(task[task_id].name);
[189]1752                    boot_puts(" in vspace ");
[228]1753                    boot_puts(vspace[vspace_id].name);
[189]1754                    boot_puts("\n");
1755                    boot_exit();
1756                }
[238]1757                ctx_dma = cluster_id * NB_DMA_CHANNELS + alloc_dma_channel[cluster_id];
[218]1758                alloc_dma_channel[cluster_id]++;
[189]1759            }
[199]1760            // ctx_epc : Get the virtual address of the start function
[238]1761            mapping_vobj_t* pvobj = &vobj[vspace[vspace_id].vobj_offset + 
1762                                     vspace[vspace_id].start_offset];
1763            unsigned int* start_vector_vbase = (unsigned int *) pvobj->vaddr;
[199]1764            unsigned int ctx_epc = start_vector_vbase[task[task_id].startid];
[189]1765
[199]1766            // ctx_sp :  Get the vobj containing the stack
[232]1767            unsigned int vobj_id = task[task_id].stack_vobjid + vspace[vspace_id].vobj_offset;
[199]1768            unsigned int ctx_sp = vobj[vobj_id].vaddr + vobj[vobj_id].length;
[189]1769
[238]1770            // get local task index in scheduler
1771            unsigned int ltid = psched->tasks;
[189]1772
[238]1773            if (ltid >= IDLE_TASK_INDEX) 
1774            {
[197]1775                boot_puts("\n[BOOT ERROR] : ");
[228]1776                boot_putd(ltid);
[197]1777                boot_puts(" tasks allocated to processor ");
[228]1778                boot_putd(gpid);
[197]1779                boot_puts(" / max is 15\n");
[189]1780                boot_exit();
1781            }
[238]1782            // update the "tasks" field in scheduler
1783            psched->tasks = ltid + 1;
[189]1784
[238]1785            // update the "current" field in scheduler
1786            psched->current = 0;
[189]1787
[238]1788            // initializes the task context in scheduler
1789            psched->context[ltid][CTX_SR_ID]    = ctx_sr;
1790            psched->context[ltid][CTX_SP_ID]    = ctx_sp;
1791            psched->context[ltid][CTX_RA_ID]    = ctx_ra;
1792            psched->context[ltid][CTX_EPC_ID]   = ctx_epc;
1793            psched->context[ltid][CTX_PTPR_ID]  = ctx_ptpr;
1794            psched->context[ltid][CTX_TTY_ID]   = ctx_tty;
1795            psched->context[ltid][CTX_CMA_ID]   = ctx_cma;
1796            psched->context[ltid][CTX_IOC_ID]   = ctx_ioc;
1797            psched->context[ltid][CTX_NIC_ID]   = ctx_nic;
1798            psched->context[ltid][CTX_TIM_ID]   = ctx_tim;
1799            psched->context[ltid][CTX_DMA_ID]   = ctx_dma;
1800            psched->context[ltid][CTX_PTAB_ID]  = ctx_ptab;
1801            psched->context[ltid][CTX_LTID_ID]  = ltid;
1802            psched->context[ltid][CTX_GTID_ID]  = task_id;
1803            psched->context[ltid][CTX_VSID_ID]  = vspace_id;
1804            psched->context[ltid][CTX_RUN_ID]   = 1;
[228]1805
[189]1806#if BOOT_DEBUG_SCHED
[238]1807boot_puts("\nTask ");
1808boot_puts(task[task_id].name);
1809boot_puts(" (");
1810boot_putd(task_id);
1811boot_puts(") allocated to processor ");
1812boot_putd(gpid);
1813boot_puts("\n  - ctx[LTID]   = ");
1814boot_putd(ltid);
1815boot_puts("\n  - ctx[SR]     = ");
1816boot_putx(ctx_sr);
1817boot_puts("\n  - ctx[SR]     = ");
1818boot_putx(ctx_sp);
1819boot_puts("\n  - ctx[RA]     = ");
1820boot_putx(ctx_ra);
1821boot_puts("\n  - ctx[EPC]    = ");
1822boot_putx(ctx_epc);
1823boot_puts("\n  - ctx[PTPR]   = ");
1824boot_putx(ctx_ptpr);
1825boot_puts("\n  - ctx[TTY]    = ");
1826boot_putd(ctx_tty);
1827boot_puts("\n  - ctx[NIC]    = ");
1828boot_putd(ctx_nic);
1829boot_puts("\n  - ctx[CMA]    = ");
1830boot_putd(ctx_cma);
1831boot_puts("\n  - ctx[IOC]    = ");
1832boot_putd(ctx_ioc);
1833boot_puts("\n  - ctx[TIM]    = ");
1834boot_putd(ctx_tim);
1835boot_puts("\n  - ctx[DMA]    = ");
1836boot_putd(ctx_dma);
1837boot_puts("\n  - ctx[PTAB]   = ");
1838boot_putx(ctx_ptab);
1839boot_puts("\n  - ctx[GTID]   = ");
1840boot_putd(task_id);
1841boot_puts("\n  - ctx[VSID]   = ");
1842boot_putd(vspace_id);
1843boot_puts("\n");
[189]1844#endif
1845
1846        } // end loop on tasks
1847    } // end loop on vspaces
1848} // end boot_schedulers_init()
1849
[228]1850
[189]1851//////////////////////////////////////////////////////////////////////////////////
1852// This function is executed by P[0] to wakeup all processors.
1853//////////////////////////////////////////////////////////////////////////////////
[238]1854void boot_start_all_procs() 
1855{
[228]1856    mapping_header_t * header = (mapping_header_t *) &seg_mapping_base;
[189]1857    header->signature = OUT_MAPPING_SIGNATURE;
1858}
1859
[228]1860
[189]1861/////////////////////////////////////////////////////////////////////
1862// This function is the entry point of the initialisation procedure
1863/////////////////////////////////////////////////////////////////////
[228]1864void boot_init() {
[236]1865
[189]1866    // mapping_info checking
1867    boot_check_mapping();
1868
1869    boot_puts("\n[BOOT] Mapping check completed at cycle ");
[228]1870    boot_putd(boot_proctime());
[189]1871    boot_puts("\n");
1872
1873    // pseg allocators initialisation
1874    boot_psegs_init();
1875
[238]1876    boot_puts("\n[BOOT] Pseg allocators initialisation completed at cycle ");
[228]1877    boot_putd(boot_proctime());
[189]1878    boot_puts("\n");
1879
[200]1880    // page table building
1881    boot_pt_init();
[189]1882
[200]1883    boot_puts("\n[BOOT] Page Tables initialisation completed at cycle ");
[228]1884    boot_putd(boot_proctime());
[189]1885    boot_puts("\n");
1886
[238]1887    // mmu activation ( with page table [Ø] )
[246]1888    boot_set_mmu_ptpr((unsigned int) (boot_ptabs_paddr[0] >> 13));
[238]1889    boot_set_mmu_mode(0xF);
1890
1891    boot_puts("\n[BOOT] Proc 0 MMU activation at cycle ");
1892    boot_putd(boot_proctime());
1893    boot_puts("\n");
1894
[246]1895
[200]1896    // vobjs initialisation
1897    boot_vobjs_init();
[189]1898
[200]1899    boot_puts("\n[BOOT] Vobjs initialisation completed at cycle : ");
[228]1900    boot_putd(boot_proctime());
[189]1901    boot_puts("\n");
1902
[200]1903    // peripherals initialisation
1904    boot_peripherals_init();
1905
1906    boot_puts("\n[BOOT] Peripherals initialisation completed at cycle ");
[228]1907    boot_putd(boot_proctime());
[200]1908    boot_puts("\n");
1909
[189]1910    // schedulers initialisation
1911    boot_schedulers_init();
1912
1913    boot_puts("\n[BOOT] Schedulers initialisation completed at cycle ");
[228]1914    boot_putd(boot_proctime());
[189]1915    boot_puts("\n");
1916
1917    // start all processors
1918    boot_start_all_procs();
1919
1920} // end boot_init()
1921
[228]1922
[189]1923// Local Variables:
1924// tab-width: 4
1925// c-basic-offset: 4
1926// c-file-offsets:((innamespace . 0)(inline-open . 0))
1927// indent-tabs-mode: nil
1928// End:
[228]1929// vim: filetype=c:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
[189]1930
Note: See TracBrowser for help on using the repository browser.