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

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

Avoid incremmentinting Pseg of "PERI" type, to permit multiple mapping.

File size: 67.1 KB
Line 
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,
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,
29//
30// The page table are statically build in the boot phase, and they do not
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
34// computed during the boot phase.
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{
288    unsigned int* tty_address = (unsigned int*)( (char*)&seg_tty_base +
289                                (CLUSTER_IO_ID * (unsigned)CLUSTER_SIZE) );
290    unsigned int n;
291
292    for ( n=0; n<100; n++)
293    {
294        if (buffer[n] == 0) break;
295        tty_address[TTY_WRITE] = (unsigned int)buffer[n];
296    }
297} 
298////////////////////////////////////////////////////////////////////////////
299// boot_putx()
300// (it uses TTY0)
301////////////////////////////////////////////////////////////////////////////
302void boot_putx(unsigned int val)
303{
304    static const char   HexaTab[] = "0123456789ABCDEF";
305    char                buf[11];
306    unsigned int        c;
307
308    buf[0]  = '0';
309    buf[1]  = 'x';
310    buf[10] = 0;
311
312    for ( c = 0 ; c < 8 ; c++ )
313    { 
314        buf[9-c] = HexaTab[val&0xF];
315        val = val >> 4;
316    }
317    boot_puts(buf);
318}
319////////////////////////////////////////////////////////////////////////////
320// boot_putd()
321// (it uses TTY0)
322////////////////////////////////////////////////////////////////////////////
323void boot_putd(unsigned int val)
324{
325    static const char   DecTab[] = "0123456789";
326    char                buf[11];
327    unsigned int        i;
328    unsigned int        first;
329
330    buf[10] = 0;
331
332    for ( i = 0 ; i < 10 ; i++ )
333    {
334        if ((val != 0) || (i == 0))
335        {
336            buf[9-i] = DecTab[val % 10];
337            first    = 9-i;
338        }
339        else
340        {
341            break;
342        }
343        val /= 10;
344    }
345    boot_puts( &buf[first] );
346}
347
348/////////////////////////////////////////////////////////////////////////////
349//  mapping_info data structure access functions
350/////////////////////////////////////////////////////////////////////////////
351inline mapping_cluster_t* boot_get_cluster_base( mapping_header_t* header )
352{
353    return   (mapping_cluster_t*) ((char*)header +
354                                  MAPPING_HEADER_SIZE);
355}
356/////////////////////////////////////////////////////////////////////////////
357inline mapping_pseg_t* boot_get_pseg_base( mapping_header_t* header )
358{
359    return   (mapping_pseg_t*)    ((char*)header +
360                                  MAPPING_HEADER_SIZE +
361                                  MAPPING_CLUSTER_SIZE*header->clusters);
362}
363/////////////////////////////////////////////////////////////////////////////
364inline mapping_vspace_t* boot_get_vspace_base( mapping_header_t* header )
365{
366    return   (mapping_vspace_t*)  ((char*)header +
367                                  MAPPING_HEADER_SIZE +
368                                  MAPPING_CLUSTER_SIZE*header->clusters +
369                                  MAPPING_PSEG_SIZE*header->psegs);
370}
371/////////////////////////////////////////////////////////////////////////////
372inline mapping_vseg_t* boot_get_vseg_base( mapping_header_t* header )
373{
374    return   (mapping_vseg_t*)    ((char*)header +
375                                  MAPPING_HEADER_SIZE +
376                                  MAPPING_CLUSTER_SIZE*header->clusters +
377                                  MAPPING_PSEG_SIZE*header->psegs +
378                                  MAPPING_VSPACE_SIZE*header->vspaces);
379}
380/////////////////////////////////////////////////////////////////////////////
381inline mapping_vobj_t* boot_get_vobj_base( mapping_header_t* header )
382{
383    return   (mapping_vobj_t*)   ((char*)header +
384                                  MAPPING_HEADER_SIZE +
385                                  MAPPING_CLUSTER_SIZE*header->clusters +
386                                  MAPPING_PSEG_SIZE*header->psegs +
387                                  MAPPING_VSPACE_SIZE*header->vspaces +
388                                  MAPPING_VSEG_SIZE*header->vsegs );
389}
390/////////////////////////////////////////////////////////////////////////////
391inline mapping_task_t* boot_get_task_base( mapping_header_t* header )
392{
393    return   (mapping_task_t*)    ((char*)header +
394                                  MAPPING_HEADER_SIZE +
395                                  MAPPING_CLUSTER_SIZE*header->clusters +
396                                  MAPPING_PSEG_SIZE*header->psegs +
397                                  MAPPING_VSPACE_SIZE*header->vspaces +
398                                  MAPPING_VSEG_SIZE*header->vsegs +
399                                  MAPPING_VOBJ_SIZE*header->vobjs );
400}
401/////////////////////////////////////////////////////////////////////////////
402inline mapping_proc_t* boot_get_proc_base( mapping_header_t* header )
403{
404    return   (mapping_proc_t*)    ((char*)header +
405                                  MAPPING_HEADER_SIZE +
406                                  MAPPING_CLUSTER_SIZE*header->clusters +
407                                  MAPPING_PSEG_SIZE*header->psegs +
408                                  MAPPING_VSPACE_SIZE*header->vspaces +
409                                  MAPPING_VSEG_SIZE*header->vsegs +
410                                  MAPPING_VOBJ_SIZE*header->vobjs +
411                                  MAPPING_TASK_SIZE*header->tasks );
412}
413/////////////////////////////////////////////////////////////////////////////
414inline mapping_irq_t* boot_get_irq_base( mapping_header_t* header )
415{
416    return   (mapping_irq_t*)     ((char*)header +
417                                  MAPPING_HEADER_SIZE +
418                                  MAPPING_CLUSTER_SIZE*header->clusters +
419                                  MAPPING_PSEG_SIZE*header->psegs +
420                                  MAPPING_VSPACE_SIZE*header->vspaces +
421                                  MAPPING_VSEG_SIZE*header->vsegs +
422                                  MAPPING_VOBJ_SIZE*header->vobjs +
423                                  MAPPING_TASK_SIZE*header->tasks +
424                                  MAPPING_PROC_SIZE*header->procs );
425}
426/////////////////////////////////////////////////////////////////////////////
427inline mapping_coproc_t* boot_get_coproc_base( mapping_header_t* header )
428{
429    return  (mapping_coproc_t*)   ((char*)header +
430                                  MAPPING_HEADER_SIZE +
431                                  MAPPING_CLUSTER_SIZE*header->clusters +
432                                  MAPPING_PSEG_SIZE*header->psegs +
433                                  MAPPING_VSPACE_SIZE*header->vspaces +
434                                  MAPPING_VOBJ_SIZE*header->vobjs +
435                                  MAPPING_VSEG_SIZE*header->vsegs +
436                                  MAPPING_TASK_SIZE*header->tasks +
437                                  MAPPING_PROC_SIZE*header->procs +
438                                  MAPPING_IRQ_SIZE*header->irqs );
439}
440///////////////////////////////////////////////////////////////////////////////////
441inline mapping_cp_port_t* boot_get_cp_port_base( mapping_header_t* header )
442{
443    return (mapping_cp_port_t*)   ((char*)header +
444                                  MAPPING_HEADER_SIZE +
445                                  MAPPING_CLUSTER_SIZE*header->clusters +
446                                  MAPPING_PSEG_SIZE*header->psegs +
447                                  MAPPING_VSPACE_SIZE*header->vspaces +
448                                  MAPPING_VOBJ_SIZE*header->vobjs +
449                                  MAPPING_VSEG_SIZE*header->vsegs +
450                                  MAPPING_TASK_SIZE*header->tasks +
451                                  MAPPING_PROC_SIZE*header->procs +
452                                  MAPPING_IRQ_SIZE*header->irqs +
453                                  MAPPING_COPROC_SIZE*header->coprocs );
454}
455///////////////////////////////////////////////////////////////////////////////////
456inline mapping_periph_t* boot_get_periph_base( mapping_header_t* header )
457{
458    return (mapping_periph_t*)    ((char*)header +
459                                  MAPPING_HEADER_SIZE +
460                                  MAPPING_CLUSTER_SIZE*header->clusters +
461                                  MAPPING_PSEG_SIZE*header->psegs +
462                                  MAPPING_VSPACE_SIZE*header->vspaces +
463                                  MAPPING_VOBJ_SIZE*header->vobjs +
464                                  MAPPING_VSEG_SIZE*header->vsegs +
465                                  MAPPING_TASK_SIZE*header->tasks +
466                                  MAPPING_PROC_SIZE*header->procs +
467                                  MAPPING_IRQ_SIZE*header->irqs +
468                                  MAPPING_COPROC_SIZE*header->coprocs +
469                                  MAPPING_CP_PORT_SIZE*header->cp_ports );
470}
471
472//////////////////////////////////////////////////////////////////////////////
473//     boot_pseg_get()
474// This function returns the pointer on a physical segment
475// identified  by the pseg index.
476//////////////////////////////////////////////////////////////////////////////
477mapping_pseg_t* boot_pseg_get( unsigned int seg_id)
478{
479    mapping_header_t* header = (mapping_header_t*)&seg_mapping_base;
480    mapping_pseg_t*   pseg   = boot_get_pseg_base( header );
481
482    // checking argument
483    if ( seg_id >= header->psegs )
484    {
485        boot_puts("\n[BOOT ERROR] : seg_id argument too large\n");
486        boot_puts("               in function boot_pseg_get()\n");
487        boot_exit();
488    }
489
490    return &pseg[seg_id];                                   
491} // end boot_pseg_get()
492
493//////////////////////////////////////////////////////////////////////////////
494// boot_add_pte()
495// This function registers a new PTE in the page table pointed
496// by the vspace_id argument, and updates both PT1 and PT2.
497// A new PT2 is used when required.
498// As the set of PT2s is implemented as a fixed size array (no dynamic
499// allocation), this function checks a possible overflow of the PT2 array.
500//
501// The global parameter is a boolean indicating wether a global vseg is
502// being mapped.
503//////////////////////////////////////////////////////////////////////////////
504void boot_add_pte( unsigned int    vspace_id,   
505                   unsigned int    vpn,           
506                   unsigned int    flags,
507                   unsigned int    ppn )
508{
509    unsigned int    ix1;
510    unsigned int    ix2;
511    unsigned int    ptba;       // PT2 base address
512    unsigned int    pt2_id;     // PT2 index
513    unsigned int*   pt_flags;   // pointer on the pte_flags = &PT2[2*ix2]   
514    unsigned int*   pt_ppn;     // pointer on the pte_ppn   = &PT2[2*ix2+1] 
515
516    ix1 = vpn >> 9;             // 11 bits
517    ix2 = vpn  & 0x1FF;         //  9 bits
518
519    // check that the boot_max_pt2[vspace_id] has been set
520    unsigned int max_pt2   = boot_max_pt2[vspace_id];
521
522    if(max_pt2 == 0)
523    {
524        boot_puts("Unfound page table for vspace ");
525        boot_putd(vspace_id);
526        boot_puts("\n");
527        boot_exit();
528    }
529
530    // get page table physical address
531    page_table_t* pt = boot_ptabs_paddr[vspace_id];
532
533    if ( (pt->pt1[ix1] & PTE_V) == 0 )   // set a new PTD in PT1
534    {
535        pt2_id = boot_next_free_pt2[vspace_id];
536        if ( pt2_id == max_pt2 )
537        {
538            boot_puts("\n[BOOT ERROR] in boot_add_pte() function\n");
539            boot_puts("the length of the ptab vobj is too small\n"); 
540            boot_exit();
541        }
542        else
543        {
544            ptba = (unsigned int)pt + PT1_SIZE + PT2_SIZE*pt2_id;
545            pt->pt1[ix1] = PTE_V | PTE_T | (ptba >> 12);   
546            boot_next_free_pt2[vspace_id] = pt2_id + 1;
547        }
548    }
549    else
550    {
551        ptba = pt->pt1[ix1] << 12;
552    }
553
554    // set PTE2 after checking double mapping error
555    pt_flags = (unsigned int*)(ptba + 8*ix2);
556    pt_ppn   = (unsigned int*)(ptba + 8*ix2 + 4);
557
558    if ( ( *pt_flags & PTE_V) != 0 )    // page already mapped
559    {
560        boot_puts("\n[BOOT ERROR] double mapping in vspace ");
561        boot_putd( vspace_id );
562        boot_puts(" for vpn = ");
563        boot_putx( vpn );
564        boot_puts("\n");
565        boot_exit();
566    }
567
568    // set PTE2
569    *pt_flags = flags;
570    *pt_ppn   = ppn;
571
572} // end boot_add_pte()
573               
574/////////////////////////////////////////////////////////////////////
575// This function build the page table for a given vspace.
576// The physical base addresses for all vsegs (global and private)
577// must have been previously computed.
578// It initializes the MWMR channels.
579/////////////////////////////////////////////////////////////////////
580void boot_vspace_pt_build( unsigned int vspace_id )
581{
582    unsigned int    vseg_id;
583    unsigned int    npages;
584    unsigned int    ppn;
585    unsigned int    vpn;
586    unsigned int    flags;
587    unsigned int    page_id;
588
589    mapping_header_t*  header = (mapping_header_t*)&seg_mapping_base; 
590    mapping_vspace_t*  vspace = boot_get_vspace_base( header );
591    mapping_vseg_t*    vseg   = boot_get_vseg_base( header );
592   
593    // private segments
594    for ( vseg_id = vspace[vspace_id].vseg_offset ; 
595          vseg_id < (vspace[vspace_id].vseg_offset + vspace[vspace_id].vsegs) ; 
596          vseg_id++ )
597    {
598        vpn       = vseg[vseg_id].vbase >> 12;
599        ppn       = vseg[vseg_id].pbase >> 12;
600        npages    = vseg[vseg_id].length >> 12;
601        if ( (vseg[vseg_id].length & 0xFFF) != 0 ) npages++;
602
603        flags = PTE_V;
604        if ( vseg[vseg_id].mode & C_MODE_MASK )  flags = flags | PTE_C;
605        if ( vseg[vseg_id].mode & X_MODE_MASK )  flags = flags | PTE_X;
606        if ( vseg[vseg_id].mode & W_MODE_MASK )  flags = flags | PTE_W;
607        if ( vseg[vseg_id].mode & U_MODE_MASK )  flags = flags | PTE_U;
608
609#if BOOT_DEBUG_PT
610boot_puts( vseg[vseg_id].name );
611boot_puts(" : flags = ");
612boot_putx( flags );
613boot_puts(" / npages = ");
614boot_putd( npages );
615boot_puts(" / pbase = ");
616boot_putx( vseg[vseg_id].pbase );
617boot_puts("\n");
618#endif       
619        // loop on 4K pages
620        for ( page_id = 0 ; page_id < npages ; page_id++ )
621        {
622            boot_add_pte( vspace_id,
623                          vpn,
624                          flags,
625                          ppn );
626            vpn++;
627            ppn++;
628        }
629    }
630
631    // global segments
632    for ( vseg_id = 0 ; vseg_id < header->globals ; vseg_id++ )
633    {
634        vpn       = vseg[vseg_id].vbase >> 12;
635        ppn       = vseg[vseg_id].pbase >> 12;
636        npages    = vseg[vseg_id].length >> 12;
637        if ( (vseg[vseg_id].length & 0xFFF) != 0 ) npages++;
638
639        flags = PTE_V;
640        if ( vseg[vseg_id].mode & C_MODE_MASK )  flags = flags | PTE_C;
641        if ( vseg[vseg_id].mode & X_MODE_MASK )  flags = flags | PTE_X;
642        if ( vseg[vseg_id].mode & W_MODE_MASK )  flags = flags | PTE_W;
643        if ( vseg[vseg_id].mode & U_MODE_MASK )  flags = flags | PTE_U;
644
645#if BOOT_DEBUG_PT
646boot_puts( vseg[vseg_id].name );
647boot_puts(" / flags = ");
648boot_putx( flags );
649boot_puts(" / npages = ");
650boot_putd( npages );
651boot_puts(" / pbase = ");
652boot_putx( vseg[vseg_id].pbase );
653boot_puts("\n");
654#endif       
655        // loop on 4K pages
656        for ( page_id = 0 ; page_id < npages ; page_id++ )
657        {
658            boot_add_pte( vspace_id,
659                          vpn,
660                          flags,
661                          ppn );
662            vpn++;
663            ppn++;
664        }
665    }
666
667} // end boot_vspace_pt_build()
668
669///////////////////////////////////////////////////////////////////////////
670// Align the value "toAlign" to the required alignement indicated by
671// alignPow2 ( the logarithme of 2 the alignement).
672///////////////////////////////////////////////////////////////////////////
673unsigned int align_to( unsigned int toAlign, 
674                       unsigned int alignPow2)
675{
676    unsigned int    mask = (1 << alignPow2) - 1;
677    return ((toAlign + mask ) & ~mask ); 
678}
679
680///////////////////////////////////////////////////////////////////////////
681// This function compute the physical base address for a vseg
682// as specified in the mapping info data structure.
683// It updates the pbase and the length fields of the vseg.
684// It updates the pbase and vbase fields of all vobjs in the vseg.
685// It updates the next_base field of the pseg, and checks overflow.
686// It updates the boot_ptabs_paddr[] and boot_ptabs_vaddr[] arrays.
687// It is a global vseg if vspace_id = (-1).
688///////////////////////////////////////////////////////////////////////////
689void boot_vseg_map( mapping_vseg_t*     vseg, 
690                    unsigned int        vspace_id ) 
691{
692    unsigned int        vobj_id;
693    unsigned int        cur_vaddr;
694    unsigned int        cur_paddr;
695    mapping_header_t*   header = (mapping_header_t*)&seg_mapping_base; 
696    mapping_vobj_t*     vobj   = boot_get_vobj_base( header );
697 
698    // get physical segment pointer
699    mapping_pseg_t*  pseg = boot_pseg_get( vseg->psegid );
700
701    // compute vseg physical base address
702    if ( vseg->ident != 0 )            // identity mapping required
703    {
704         vseg->pbase = vseg->vbase;
705    }
706    else                                // unconstrained mapping
707    {
708        vseg->pbase = pseg->next_base;
709
710        // test alignment constraint
711        if ( vobj[vseg->vobj_offset].align )
712        {
713            vseg->pbase = align_to( vseg->pbase, vobj[vseg->vobj_offset].align );
714        }
715    }
716   
717    // loop on vobjs contained in vseg to :
718    // (1) computes the length of the vseg,
719    // (2) initialise the vaddr and paddr fields of all vobjs,
720    // (3) initialise the page table pointers arrays
721
722    cur_vaddr = vseg->vbase;
723    cur_paddr = vseg->pbase;
724
725    for( vobj_id = vseg->vobj_offset; 
726         vobj_id < (vseg->vobj_offset + vseg->vobjs); 
727         vobj_id++)
728    {
729        if ( vobj[vobj_id].align )
730        {
731            cur_paddr = align_to(cur_paddr, vobj[vobj_id].align);
732        }
733
734        // set vaddr/paddr for current vobj
735        vobj[vobj_id].vaddr = cur_vaddr;       
736        vobj[vobj_id].paddr = cur_paddr; 
737     
738        // initialise boot_ptabs_vaddr[] if current vobj is a PTAB
739        if ( vobj[vobj_id].type == VOBJ_TYPE_PTAB )
740        {
741            if(vspace_id == ((unsigned int) -1))    // global vseg
742            {
743                boot_puts( "\n[BOOT ERROR] in boot_vseg_map() function: " );
744                boot_puts( "a PTAB vobj cannot be global" );
745                boot_exit();
746            }
747
748            // we need at least one PT2 => ( boot_max_pt2[vspace_id] >= 1)
749            if(vobj[vobj_id].length < (PT1_SIZE + PT2_SIZE) ) 
750            {
751                boot_puts( "\n[BOOT ERROR] in boot_vseg_map() function, " );
752                boot_puts("PTAB too small, minumum size is: ");
753                boot_putx( PT1_SIZE + PT2_SIZE);
754                boot_exit();
755            }
756
757            // register both physical and virtual page table address
758            boot_ptabs_vaddr[vspace_id] = (page_table_t*)vobj[vobj_id].vaddr;
759            boot_ptabs_paddr[vspace_id] = (page_table_t*)vobj[vobj_id].paddr;
760
761            /* computing the number of second level page */
762            boot_max_pt2[vspace_id] = (vobj[vobj_id].length - PT1_SIZE) / PT2_SIZE;
763        }
764
765        // set next vaddr/paddr
766        cur_vaddr += vobj[vobj_id].length;
767        cur_paddr += vobj[vobj_id].length; 
768
769    } // end for vobjs
770   
771    //set the vseg length
772    vseg->length = align_to( (cur_paddr - vseg->pbase), 12);
773
774    // checking pseg overflow
775    if ( (vseg->pbase < pseg->base) || 
776         ((vseg->pbase + vseg->length) > (pseg->base + pseg->length)) )
777    {
778        boot_puts("\n[BOOT ERROR] in boot_vseg_map() function\n");
779        boot_puts("impossible mapping for virtual segment: ");
780        boot_puts( vseg->name ); 
781        boot_puts("\n"); 
782        boot_puts("vseg pbase = ");
783        boot_putx( vseg->pbase ); 
784        boot_puts("\n"); 
785        boot_puts("vseg length = ");
786        boot_putx( vseg->length ); 
787        boot_puts("\n"); 
788        boot_puts("pseg pbase = ");
789        boot_putx( pseg->base ); 
790        boot_puts("\n"); 
791        boot_puts("pseg length = ");
792        boot_putx( pseg->length ); 
793        boot_puts("\n"); 
794        boot_exit();
795    }
796
797
798#if BOOT_DEBUG_PT
799boot_puts( vseg->name );
800boot_puts(" : len = ");
801boot_putx( vseg->length );
802boot_puts(" / vbase = ");
803boot_putx( vseg->vbase );
804boot_puts(" / pbase = ");
805boot_putx( vseg->pbase );
806boot_puts("\n");
807#endif 
808
809    // set the next_base field in vseg
810    if ( vseg->ident == 0 && pseg->type != PSEG_TYPE_PERI )
811        pseg->next_base = vseg->pbase + vseg->length;
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: ");
829        boot_putx(header->signature);
830        boot_puts("\n");
831        boot_exit();
832    }
833
834    // checking number of clusters
835    if ( header->clusters != NB_CLUSTERS )
836    {
837        boot_puts("\n[BOOT ERROR] Incoherent NB_CLUSTERS");
838        boot_puts("\n             - In giet_config,  value = ");
839        boot_putd ( NB_CLUSTERS );
840        boot_puts("\n             - In mapping_info, value = ");
841        boot_putd ( header->clusters );
842        boot_puts("\n");
843        boot_exit();
844    }
845
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
854    // checking hardware
855    unsigned int periph_id;
856    unsigned int cluster_id;
857    unsigned int tty_found = 0;
858    unsigned int nic_found = 0;
859    for ( cluster_id = 0 ; cluster_id < NB_CLUSTERS ; cluster_id++ )
860    {
861        // NB_PROCS_MAX
862        if ( cluster[cluster_id].procs > NB_PROCS_MAX )
863        {
864            boot_puts("\n[BOOT ERROR] too much processors in cluster ");
865            boot_putd( cluster_id );
866            boot_puts(" : procs = ");
867            boot_putd ( cluster[cluster_id].procs );
868            boot_puts("\n");
869            boot_exit();
870        }
871
872        for ( periph_id = cluster[cluster_id].periph_offset ;
873              periph_id < cluster[cluster_id].periph_offset + cluster[cluster_id].periphs ;
874              periph_id++ )
875        {
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                }
884                if ( periph[periph_id].channels != NB_TTYS )
885                {
886                    boot_puts("\n[BOOT ERROR] Wrong NB_TTYS in cluster ");
887                    boot_putd( cluster_id );
888                    boot_puts(" : ttys = ");
889                    boot_putd ( periph[periph_id].channels );
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                }
903                if ( periph[periph_id].channels != NB_NICS )
904                {
905                    boot_puts("\n[BOOT ERROR] Wrong NB_NICS in cluster ");
906                    boot_putd( cluster_id );
907                    boot_puts(" : nics = ");
908                    boot_putd ( periph[periph_id].channels );
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            {
917                if ( periph[periph_id].channels != (NB_PROCS_MAX + NB_TIMERS_MAX) )
918                {
919                    boot_puts("\n[BOOT ERROR] Too much user timers in cluster ");
920                    boot_putd( cluster_id );
921                    boot_puts(" : timers = ");
922                    boot_putd ( periph[periph_id].channels );
923                    boot_puts("\n");
924                    boot_exit();
925                }
926            }
927            // NB_DMAS
928            if ( periph[periph_id].type == PERIPH_TYPE_DMA ) 
929            {
930                if ( periph[periph_id].channels != NB_DMAS_MAX )
931                {
932                    boot_puts("\n[BOOT ERROR] Too much DMA channels in cluster ");
933                    boot_putd( cluster_id );
934                    boot_puts(" : channels = ");
935                    boot_putd ( periph[periph_id].channels );
936                    boot_puts("\n");
937                    boot_exit();
938                }
939            }
940        } // end for periphs
941    } // end for clusters
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 ");
970            boot_putd( cluster_id );
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 ");
992boot_putd(cluster_id);
993boot_puts(" / pseg ");
994boot_puts(pseg[pseg_id].name);
995boot_puts(" : next_base = ");
996boot_putx(pseg[pseg_id].next_base);
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 = ");
1061boot_putx((unsigned int)boot_ptabs_paddr[vspace_id]);
1062boot_puts(", page table number of PT2 = ");
1063boot_putd((unsigned int)boot_max_pt2[vspace_id]);
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                        {
1104                    mwmr_channel_t* mwmr = (mwmr_channel_t*)(vobj[vobj_id].paddr);
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 = ");
1115boot_putd( mwmr->depth );
1116boot_puts(" / width = ");
1117boot_putd( mwmr->width );
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 = ");
1128boot_putx( vobj[vobj_id].length ); 
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 = ");
1139boot_putx( vobj[vobj_id].length ); 
1140boot_puts("\n");
1141#endif
1142                    break;
1143                }
1144                case VOBJ_TYPE_BARRIER: // init is the number of participants
1145                {
1146                    giet_barrier_t* barrier = (giet_barrier_t*)(vobj[vobj_id].paddr);
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 = ");
1153boot_putd( barrier->init );
1154boot_puts("\n");
1155#endif
1156                    break;
1157                }
1158                case VOBJ_TYPE_LOCK:    // init is "not taken"
1159                {
1160                    unsigned int* lock = (unsigned int*)(vobj[vobj_id].paddr);
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 = ");
1175boot_putx( vobj[vobj_id].length ); 
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 = ");
1187boot_putx( vobj[vobj_id].length ); 
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 ");
1206            boot_putd( vspace_id );
1207            boot_exit();
1208        }
1209    } // end loop on vspaces
1210} // end boot_vobjs_init()
1211
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
1228////////////////////////////////////////////////////////////////////////////////
1229// This function intializes the periherals and coprocessors, as specified
1230// in the mapping_info file.
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 );
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 );
1242
1243    unsigned int        cluster_id;
1244    unsigned int        periph_id; 
1245    unsigned int        coproc_id; 
1246    unsigned int        cp_port_id; 
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 "); 
1254boot_putd( cluster_id );
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 : ");
1277boot_putd( channels );
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 : ");
1293boot_putd( channels );
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 : ");
1308boot_putd( channels );
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 : ");
1330boot_putd( channels );
1331boot_puts(" channels\n");
1332#endif
1333            }
1334
1335        } // end for periphs
1336
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        {
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 ");
1347boot_puts((unsigned int) coproc[coproc_id].name);
1348boot_puts(", nb ports");
1349boot_putd((unsigned int)coproc[coproc_id].ports);
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            {
1357                //FIXME: the vspace_id should be the same for all ports: put it in the coproc?
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            }
1387        } // end for coprocs
1388
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 ");
1449boot_putd( cluster_id );
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 ");
1472            boot_putd( cluster_id );
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 ");
1491boot_putd( proc_id );
1492boot_puts(" : scheduler pbase = ");
1493boot_putx( pseg_pbase + (proc_id<<12) );
1494boot_puts("\n");
1495#endif
1496            // initialise the "tasks" variable in scheduler
1497            boot_scheduler_set_tasks( proc_id , 0 );
1498           
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 = ");
1520boot_putd( icu_id );
1521boot_puts(" / type = ");
1522boot_putd( type );
1523boot_puts(" / isr = ");
1524boot_putd( isr_id );
1525boot_puts(" / channel = ");
1526boot_putd( channel );
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
1548        // loop on the tasks in vspace (task_id is the global index)
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        {
1553            // ctx_ra :  the return address is &boot_eret()
1554            unsigned int ctx_ra = (unsigned int)&boot_eret;
1555
1556            // ctx_sr : value required before an eret instruction
1557            unsigned int ctx_sr = 0x0000FF13; 
1558
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;
1561
1562            // ctx_ptab : page_table virtual base address
1563            unsigned int ctx_ptab = (unsigned int)boot_ptabs_vaddr[vspace_id];
1564
1565            // ctx_tty : terminal global index provided by a global allocator
1566            unsigned int ctx_tty = 0xFFFFFFFF;
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                }
1578                ctx_tty = alloc_tty_channel;
1579                alloc_tty_channel++;
1580            }
1581
1582            // ctx_nic : NIC channel global index provided by a global allocator
1583            unsigned int ctx_nic = 0xFFFFFFFF;
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                }
1595                ctx_nic = alloc_nic_channel;
1596                alloc_nic_channel++;
1597            }
1598
1599            // ctx_timer : user TIMER global index provided by a cluster allocator
1600            unsigned int ctx_timer = 0xFFFFFFFF;
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                }
1613                ctx_timer = cluster_id*NB_TIMERS_MAX + alloc_timer_channel[cluster_id];
1614                alloc_timer_channel[cluster_id]++;
1615            }
1616
1617            // ctx_fbdma : DMA global index provided by a cluster allocator 
1618            unsigned int ctx_fbdma = 0xFFFFFFFF;
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                }
1631                ctx_fbdma = cluster_id*NB_DMAS_MAX + alloc_fbdma_channel[cluster_id];
1632                alloc_fbdma_channel[cluster_id]++;
1633            }
1634
1635            // ctx_epc : Get the virtual address of the start function
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;
1639            unsigned int ctx_epc = start_vector_vbase[task[task_id].startid];
1640
1641            // ctx_sp :  Get the vobj containing the stack
1642            unsigned int vobj_id = task[task_id].vobjlocid + vspace[vspace_id].vobj_offset;
1643            unsigned int ctx_sp = vobj[vobj_id].vaddr + vobj[vobj_id].length;
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
1656            if ( ltid >= IDLE_TASK_INDEX )
1657            {
1658                boot_puts("\n[BOOT ERROR] : ");
1659                boot_putd( ltid );
1660                boot_puts(" tasks allocated to processor ");
1661                boot_putd( gpid );
1662                boot_puts(" / max is 15\n");
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]
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          );
1686                                       
1687#if BOOT_DEBUG_SCHED
1688boot_puts("\nTask ");
1689boot_puts( task[task_id].name );
1690boot_puts(" allocated to processor ");
1691boot_putd( gpid );
1692boot_puts("  - ctx[LTID]   = ");
1693boot_putd( ltid );
1694boot_puts("\n");
1695
1696boot_puts("  - ctx[SR]     = ");
1697boot_putx( ctx_sr );
1698boot_puts("\n");
1699
1700boot_puts("  - ctx[SR]     = ");
1701boot_putx( ctx_sp );
1702boot_puts("\n");
1703
1704boot_puts("  - ctx[RA]     = ");
1705boot_putx( ctx_ra );
1706boot_puts("\n");
1707
1708boot_puts("  - ctx[EPC]    = ");
1709boot_putx( ctx_epc );
1710boot_puts("\n");
1711
1712boot_puts("  - ctx[PTPR]   = ");
1713boot_putx( ctx_ptpr );
1714boot_puts("\n");
1715
1716boot_puts("  - ctx[TTY]    = ");
1717boot_putd( ctx_tty );
1718boot_puts("\n");
1719
1720boot_puts("  - ctx[NIC]    = ");
1721boot_putd( ctx_nic );
1722boot_puts("\n");
1723
1724boot_puts("  - ctx[TIMER]  = ");
1725boot_putd( ctx_timer );
1726boot_puts("\n");
1727
1728boot_puts("  - ctx[FBDMA]  = ");
1729boot_putd( ctx_fbdma );
1730boot_puts("\n");
1731
1732boot_puts("  - ctx[PTAB]   = ");
1733boot_putx( ctx_ptab );
1734boot_puts("\n");
1735
1736boot_puts("  - ctx[VSID]   = ");
1737boot_putd( vspace_id );
1738boot_puts("\n");
1739
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 ");
1764    boot_putd( boot_proctime() );
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 ");
1771    boot_putd( boot_proctime() );
1772    boot_puts("\n");
1773
1774    // page table building
1775    boot_pt_init();
1776
1777    boot_puts("\n[BOOT] Page Tables initialisation completed at cycle ");
1778    boot_putd( boot_proctime() );
1779    boot_puts("\n");
1780
1781    // vobjs initialisation
1782    boot_vobjs_init();
1783
1784    boot_puts("\n[BOOT] Vobjs initialisation completed at cycle : ");
1785    boot_putd( boot_proctime() );
1786    boot_puts("\n");
1787
1788    // peripherals initialisation
1789    boot_peripherals_init();
1790
1791    boot_puts("\n[BOOT] Peripherals initialisation completed at cycle ");
1792    boot_putd( boot_proctime() );
1793    boot_puts("\n");
1794
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 ");
1800    boot_putd( boot_proctime() );
1801    boot_puts("\n");
1802
1803    // schedulers initialisation
1804    boot_schedulers_init();
1805
1806    boot_puts("\n[BOOT] Schedulers initialisation completed at cycle ");
1807    boot_putd( boot_proctime() );
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.