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

Last change on this file since 240 was 240, checked in by joannou, 11 years ago

Bug fix for scheduler handling :

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