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

Last change on this file since 236 was 236, checked in by alain, 11 years ago

Improving trace in kernel_init()

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