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

Last change on this file since 239 was 238, checked in by alain, 11 years ago

Major evolution to support physical addresses larger than 32 bits.
The map.xml format has been modified: the vsegs associated to schedulers
are now explicitely defined and mapped in the page tables.

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