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

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

Various modifications to support IO Bridge,
and MEMC configuration interface.

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