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

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

Ajout du malloc dans le Giet.

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