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

Last change on this file since 222 was 218, checked in by alain, 12 years ago

Introducing support for Network controller

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