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

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

1/ introducing support to display images on the frame buffer
with the vci_chbuf_dma (in stdio.c and drivers.c)
2/ introducing support for mem_cache configuration segment
as the memory cache is considered as another addressable peripheral type
(in drivers.c)
3/ Introducing the new "increment" parameter in the mapping header.
This parameter define the virtual address increment for the vsegs
associated to the replicated peripherals (ICU, XICU, MDMA, TIMER, MMC).
This parameter is mandatory, and all map.xml files the "mappings"
directory have been updated.

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