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

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

Correction d'un bug lors du boot pour les alignements
Modification de l'appel SRL pour les CONST

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].vobjlocid + 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].vobjlocid + 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_RUN_ID, 1);
1709
1710#if BOOT_DEBUG_SCHED
1711            boot_puts("\nTask ");
1712            boot_puts(task[task_id].name);
1713            boot_puts(" (");
1714            boot_putd(task_id);
1715            boot_puts(") allocated to processor ");
1716            boot_putd(gpid);
1717            boot_puts("  - ctx[LTID]   = ");
1718            boot_putd(ltid);
1719            boot_puts("\n");
1720
1721            boot_puts("  - ctx[SR]     = ");
1722            boot_putx(ctx_sr);
1723            boot_puts("\n");
1724
1725            boot_puts("  - ctx[SR]     = ");
1726            boot_putx(ctx_sp);
1727            boot_puts("\n");
1728
1729            boot_puts("  - ctx[RA]     = ");
1730            boot_putx(ctx_ra);
1731            boot_puts("\n");
1732
1733            boot_puts("  - ctx[EPC]    = ");
1734            boot_putx(ctx_epc);
1735            boot_puts("\n");
1736
1737            boot_puts("  - ctx[PTPR]   = ");
1738            boot_putx(ctx_ptpr);
1739            boot_puts("\n");
1740
1741            boot_puts("  - ctx[TTY]    = ");
1742            boot_putd(ctx_tty);
1743            boot_puts("\n");
1744
1745            boot_puts("  - ctx[NIC]    = ");
1746            boot_putd(ctx_nic);
1747            boot_puts("\n");
1748
1749            boot_puts("  - ctx[TIMER]  = ");
1750            boot_putd(ctx_timer);
1751            boot_puts("\n");
1752
1753            boot_puts("  - ctx[DMA]    = ");
1754            boot_putd(ctx_dma);
1755            boot_puts("\n");
1756
1757            boot_puts("  - ctx[PTAB]   = ");
1758            boot_putx(ctx_ptab);
1759            boot_puts("\n");
1760
1761            boot_puts("  - ctx[VSID]   = ");
1762            boot_putd(vspace_id);
1763            boot_puts("\n");
1764
1765#endif
1766
1767        } // end loop on tasks
1768    } // end loop on vspaces
1769} // end boot_schedulers_init()
1770
1771
1772//////////////////////////////////////////////////////////////////////////////////
1773// This function is executed by P[0] to wakeup all processors.
1774//////////////////////////////////////////////////////////////////////////////////
1775void boot_start_all_procs() {
1776    mapping_header_t * header = (mapping_header_t *) &seg_mapping_base;
1777    header->signature = OUT_MAPPING_SIGNATURE;
1778}
1779
1780
1781/////////////////////////////////////////////////////////////////////
1782// This function is the entry point of the initialisation procedure
1783/////////////////////////////////////////////////////////////////////
1784void boot_init() {
1785    // mapping_info checking
1786    boot_check_mapping();
1787
1788    boot_puts("\n[BOOT] Mapping check completed at cycle ");
1789    boot_putd(boot_proctime());
1790    boot_puts("\n");
1791
1792    // pseg allocators initialisation
1793    boot_psegs_init();
1794
1795    boot_puts
1796        ("\n[BOOT] Pseg allocators initialisation completed at cycle ");
1797    boot_putd(boot_proctime());
1798    boot_puts("\n");
1799
1800    // page table building
1801    boot_pt_init();
1802
1803    boot_puts("\n[BOOT] Page Tables initialisation completed at cycle ");
1804    boot_putd(boot_proctime());
1805    boot_puts("\n");
1806
1807    // vobjs initialisation
1808    boot_vobjs_init();
1809
1810    boot_puts("\n[BOOT] Vobjs initialisation completed at cycle : ");
1811    boot_putd(boot_proctime());
1812    boot_puts("\n");
1813
1814    // peripherals initialisation
1815    boot_peripherals_init();
1816
1817    boot_puts("\n[BOOT] Peripherals initialisation completed at cycle ");
1818    boot_putd(boot_proctime());
1819    boot_puts("\n");
1820
1821    // mmu activation
1822    boot_set_mmu_ptpr((unsigned int) boot_ptabs_paddr[0] >> 13);
1823    boot_set_mmu_mode(0xF);
1824
1825    boot_puts("\n[BOOT] MMU activation completed at cycle ");
1826    boot_putd(boot_proctime());
1827    boot_puts("\n");
1828
1829    // schedulers initialisation
1830    boot_schedulers_init();
1831
1832    boot_puts("\n[BOOT] Schedulers initialisation completed at cycle ");
1833    boot_putd(boot_proctime());
1834    boot_puts("\n");
1835
1836    // start all processors
1837    boot_start_all_procs();
1838
1839} // end boot_init()
1840
1841
1842// Local Variables:
1843// tab-width: 4
1844// c-basic-offset: 4
1845// c-file-offsets:((innamespace . 0)(inline-open . 0))
1846// indent-tabs-mode: nil
1847// End:
1848// vim: filetype=c:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
1849
Note: See TracBrowser for help on using the repository browser.