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

Last change on this file since 206 was 205, checked in by karaoui, 12 years ago

adding the possibilité of having 0 DMA.

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