source: soft/giet_vm/boot/boot_handler.c @ 163

Last change on this file since 163 was 163, checked in by karaoui, 12 years ago

changing mover to memo
changing soft.bin to soft.elf
...

File size: 31.8 KB
Line 
1//////////////////////////////////////////////////////////////////////////////////
2// File     : boot_handler.c
3// Date     : 01/04/2012
4// Author   : alain greiner
5// Copyright (c) UPMC-LIP6
6///////////////////////////////////////////////////////////////////////////////////
7// The boot_handler.h and boot_handler.c files are part of the GIET nano-kernel.
8// This code can be used in the boot phase to build all the pages tables then jumps
9// in to the seg_kernel_init segment with an activated MMU.
10//
11// It uses the SoCLib generic MMU (paged virtual memory) to provide two services:
12//
13// 1) classical memory protection, when several independant applications compiled
14//    in different virtual spaces are executing on the same hardware platform.
15// 2) data placement in NUMA architectures, when we want to control the placement
16//    of the software objects (virtual segments) on the physical memory banks.
17//
18// It uses the MAPPING_INFO binary data structures, that must be pre-loaded in the
19// boot ROM in the seg_boot_mapping segment (at address seg_mapping_base).
20// This MAPPING_INFO data structure defines both the hardware architecture,
21// and the mapping:
22// - number of clusters,
23// - number of processors in each cluster,
24// - physical segmentation of the physical address space,
25// - number of virtual spaces (one multi-task application per vspace),
26// - static placement of tasks on the processors,
27// - static placement of virtual segments (vseg) in the physical segments (pseg).
28// - static placement of virtual objects (vobj) on virtual segments (vseg).
29//
30// The page table are statically constructed in the boot phase, and they do not
31// change during execution. The GIET uses only 4 Kbytes pages.
32// As most applications use only a limited number of segments, the number of PT2s
33// actually used by a given virtual space is generally smaller than 2048, and is
34// defined in the MAPPING_INFO_BINARY data structure(using the length field).
35// The value is calculated and put in _max_pte2 indexed by the vspace_id.
36// The physical alignment constraints, is ensured by the align flag in the MAPPING_INFO
37// structure.
38// The max number of virtual spaces (GIET_NB_VSPACE_MAX) is a configuration parameter.
39//
40// Each page table (one page table per virtual space) is monolithic:
41// - a first 8K aligned PT1[2148] array, indexed by the (ix1) field of VPN.
42//   The PT1 contains 2048 PTD of 4 bytes => 8K bytes.
43// - an aray of array PT2[1024][_max_pte2[vspace_id]], indexed by
44//   the (ix2) field of the VPN, and by the PT2 index (pt2_id).
45//   Each PT2 contains 512 PTE2 of 8bytes => 4Kbytes * _max_pte2[vspace_id]
46// The size of each page table is 8K + (_max_pte2[vspace_id])*4K bytes.
47// All page tables must be stored in the seg_kernel_pt segment (at address
48// seg_kernel_pt_base)
49////////////////////////////////////////////////////////////////////////////////////
50
51#include <mips32_registers.h>
52#include <boot_handler.h>
53#include <mapping_info.h>
54#include <mwmr.h>
55
56#include <stdarg.h>
57
58
59#if !defined(GIET_NB_VSPACE_MAX)
60# error The GIET_NB_VSPACE_MAX value must be defined in the 'giet_config.h' file !
61#endif
62
63////////////////////////////////////////////////////////////////////////////
64//  Global variables
65////////////////////////////////////////////////////////////////////////////
66
67// Page Tables
68// Next free PT2 index
69unsigned int  _next_free_pt2[GIET_NB_VSPACE_MAX] =
70                         { [0 ... GIET_NB_VSPACE_MAX-1] = 0 };
71
72// Max PT2 index
73unsigned int  _max_pte2[GIET_NB_VSPACE_MAX] =
74                         { [0 ... GIET_NB_VSPACE_MAX-1] = 0 };
75
76// Page table pointers
77page_table_t* _ptabs[GIET_NB_VSPACE_MAX];
78
79//////////////////////////////////////////////////////////////////////////////
80// boot_procid()
81//////////////////////////////////////////////////////////////////////////////
82unsigned int boot_procid()
83{
84    unsigned int ret;
85    asm volatile("mfc0 %0, $15, 1" : "=r"(ret));
86    return (ret & 0x3FF);
87}
88
89//////////////////////////////////////////////////////////////////////////////
90// boot_time()
91//////////////////////////////////////////////////////////////////////////////
92unsigned int boot_time()
93{
94    unsigned int ret;
95    asm volatile("mfc0 %0, $9" : "=r"(ret));
96    return ret;
97}
98
99//////////////////////////////////////////////////////////////////////////////
100// boot_exit()
101//////////////////////////////////////////////////////////////////////////////
102void boot_exit()
103{
104    while(1) asm volatile("nop");
105}
106
107
108////////////////////////////////////////////////////////////////////////////
109// boot_tty_puts()
110// (it uses TTY0)
111////////////////////////////////////////////////////////////////////////////
112void boot_tty_puts(const char *buffer) 
113{
114    unsigned int* tty_address = (unsigned int*)&seg_tty_base;
115    unsigned int n;
116
117    for ( n=0; n<100; n++)
118    {
119        if (buffer[n] == 0) break;
120        tty_address[0] = (unsigned int)buffer[n];
121    }
122   
123} 
124
125////////////////////////////////////////////////////////////////////////////
126// boot_tty_putw()
127// (it uses TTY0)
128////////////////////////////////////////////////////////////////////////////
129void boot_tty_putw(unsigned int val)
130{
131    static const char   HexaTab[] = "0123456789ABCDEF";
132    char                buf[11];
133    unsigned int        c;
134
135    buf[0]  = '0';
136    buf[1]  = 'x';
137    buf[10] = 0;
138
139    for ( c = 0 ; c < 8 ; c++ )
140    { 
141        buf[9-c] = HexaTab[val&0xF];
142        val = val >> 4;
143    }
144    boot_tty_puts(buf);
145}
146
147/////////////////////////////////////////////////////////////////////////////
148// various mapping_info data structure access functions
149/////////////////////////////////////////////////////////////////////////////
150mapping_cluster_t* boot_get_cluster_base( mapping_header_t* header )
151{
152    return   (mapping_cluster_t*) ((char*)header +
153                                  MAPPING_HEADER_SIZE);
154}
155/////////////////////////////////////////////////////////////////////////////
156mapping_pseg_t* boot_get_pseg_base( mapping_header_t* header )
157{
158    return   (mapping_pseg_t*)    ((char*)header +
159                                  MAPPING_HEADER_SIZE +
160                                  MAPPING_CLUSTER_SIZE*header->clusters);
161}
162/////////////////////////////////////////////////////////////////////////////
163mapping_vspace_t* boot_get_vspace_base( mapping_header_t* header )
164{
165    return   (mapping_vspace_t*)  ((char*)header +
166                                  MAPPING_HEADER_SIZE +
167                                  MAPPING_CLUSTER_SIZE*header->clusters +
168                                  MAPPING_PSEG_SIZE*header->psegs);
169}
170/////////////////////////////////////////////////////////////////////////////
171mapping_vseg_t* boot_get_vseg_base( mapping_header_t* header )
172{
173    return   (mapping_vseg_t*)    ((char*)header +
174                                  MAPPING_HEADER_SIZE +
175                                  MAPPING_CLUSTER_SIZE*header->clusters +
176                                  MAPPING_PSEG_SIZE*header->psegs +
177                                  MAPPING_VSPACE_SIZE*header->vspaces);
178}
179/////////////////////////////////////////////////////////////////////////////
180mapping_vobj_t* boot_get_vobj_base( mapping_header_t* header )
181{
182    return   (mapping_vobj_t*)   ((char*)header +
183                                  MAPPING_HEADER_SIZE +
184                                  MAPPING_CLUSTER_SIZE*header->clusters +
185                                  MAPPING_PSEG_SIZE*header->psegs +
186                                  MAPPING_VSPACE_SIZE*header->vspaces +
187                                  MAPPING_VSEG_SIZE*header->vsegs );
188}
189/////////////////////////////////////////////////////////////////////////////
190mapping_task_t* boot_get_task_base( mapping_header_t* header )
191{
192    return   (mapping_task_t*)    ((char*)header +
193                                  MAPPING_HEADER_SIZE +
194                                  MAPPING_CLUSTER_SIZE*header->clusters +
195                                  MAPPING_PSEG_SIZE*header->psegs +
196                                  MAPPING_VSPACE_SIZE*header->vspaces +
197                                  MAPPING_VOBJ_SIZE*header->vobjs +
198                                  MAPPING_VSEG_SIZE*header->vsegs);
199}
200
201/////////////////////////////////////////////////////////////////////////////
202// print the content of the mapping_info data structure
203////////////////////////////////////////////////////////////////////////
204#if BOOT_DEBUG_VIEW
205void boot_print_mapping_info()
206{
207    mapping_header_t*   header = (mapping_header_t*)&seg_mapping_base; 
208   
209    unsigned int                vspace_id;
210    unsigned int                cluster_id;
211    unsigned int                pseg_id;
212    unsigned int                vseg_id;
213    unsigned int                vobj_id;
214    unsigned int                task_id;
215
216    mapping_cluster_t*  cluster = boot_get_cluster_base( header );
217    mapping_pseg_t*         pseg    = boot_get_pseg_base( header );;
218    mapping_vspace_t*   vspace  = boot_get_vspace_base ( header );;
219    mapping_vseg_t*         vseg    = boot_get_vseg_base ( header );
220    mapping_task_t*         task    = boot_get_task_base ( header );;
221    mapping_vobj_t*    vobj   = boot_get_vobj_base( header );
222
223    // header
224    boot_tty_puts("mapping_info");
225
226    boot_tty_puts("\n - signature = ");
227    boot_tty_putw(header->signature);
228    boot_tty_puts("\n - name      = ");
229    boot_tty_puts(header->name);
230    boot_tty_puts("\n - clusters  = ");
231    boot_tty_putw(header->clusters);
232    boot_tty_puts("\n - psegs     = ");
233    boot_tty_putw(header->psegs);
234    boot_tty_puts("\n - ttys      = ");
235    boot_tty_putw(header->ttys);
236    boot_tty_puts("\n - vspaces   = ");
237    boot_tty_putw(header->vspaces);
238    boot_tty_puts("\n - globals   = ");
239    boot_tty_putw(header->globals);
240    boot_tty_puts("\n - vsegs     = ");
241    boot_tty_putw(header->vsegs);
242    boot_tty_puts("\n - tasks     = ");
243    boot_tty_putw(header->tasks);
244    boot_tty_puts("\n\n");
245
246    // clusters
247    for ( cluster_id = 0 ; cluster_id < header->clusters ; cluster_id++ )
248    {
249        boot_tty_puts("cluster ");
250        boot_tty_putw(cluster_id);
251
252        boot_tty_puts("\n - procs  = ");
253        boot_tty_putw(cluster[cluster_id].procs);
254        boot_tty_puts("\n - timers = ");
255        boot_tty_putw(cluster[cluster_id].timers);
256        boot_tty_puts("\n - dmas   = ");
257        boot_tty_putw(cluster[cluster_id].dmas);
258        boot_tty_puts("\n\n");
259    }
260
261    // psegs
262    for ( pseg_id = 0 ; pseg_id < header->psegs ; pseg_id++ )
263    {
264        boot_tty_puts("pseg ");
265        boot_tty_putw(pseg_id);
266
267        boot_tty_puts("\n - name   = ");
268        boot_tty_puts( pseg[pseg_id].name );
269        boot_tty_puts("\n - base   = ");
270        boot_tty_putw( pseg[pseg_id].base );
271        boot_tty_puts("\n - length = ");
272        boot_tty_putw( pseg[pseg_id].length );
273        boot_tty_puts("\n\n");
274    }
275
276    // globals
277    for ( vseg_id = 0 ; vseg_id < header->globals ; vseg_id++ )
278    {
279        boot_tty_puts("global vseg ");
280        boot_tty_putw(vseg_id);
281
282        boot_tty_puts("\n - name   = ");
283        boot_tty_puts( vseg[vseg_id].name );
284        boot_tty_puts("\n - vbase  = ");
285        boot_tty_putw( vseg[vseg_id].vbase );
286        boot_tty_puts("\n - length = ");
287        boot_tty_putw( vseg[vseg_id].length );
288        boot_tty_puts("\n - mode   = ");
289        boot_tty_putw( vseg[vseg_id].mode );
290        boot_tty_puts("\n - ident = ");
291        boot_tty_putw( vseg[vseg_id].ident );
292        boot_tty_puts("\n - psegname = ");
293        boot_tty_puts( pseg[vseg[vseg_id].psegid].name );
294        boot_tty_puts("\n");
295        for ( vobj_id = vseg[vseg_id].vobj_offset ; vobj_id < vseg[vseg_id].vobj_offset + vseg[vseg_id].vobjs ; vobj_id++ )
296        {
297                        boot_tty_puts("vobjs: \n");
298            boot_tty_putw( vobj[vobj_id].name);
299            boot_tty_puts("\n");
300            boot_tty_puts("\t name     = ");
301                        boot_tty_putw(  vobj[vobj_id].name);
302                        boot_tty_puts("\n");
303            boot_tty_puts("\t type     = ");
304                        boot_tty_putw( vobj[vobj_id].type);
305                        boot_tty_puts("\n");
306            boot_tty_puts("\t length   = ");
307                        boot_tty_putw(   vobj[vobj_id].length);
308                        boot_tty_puts("\n");
309            boot_tty_puts("\t align    = ");
310                        boot_tty_putw(   vobj[vobj_id].align);
311                        boot_tty_puts("\n");
312            boot_tty_puts("\t binpath  = ");
313                        boot_tty_putw(   vobj[vobj_id].binpath);
314                        boot_tty_puts("\n\n");
315        }
316    }
317
318    // vspaces
319    for ( vspace_id = 0 ; vspace_id < header->vspaces ; vspace_id++ )
320    {
321        unsigned int func_id = vspace[vspace_id].vobj_offset + vspace[vspace_id].funcs_offset; 
322        boot_tty_puts("vspace ");
323        boot_tty_putw(vspace_id);
324
325        boot_tty_puts("\n - name    = ");
326        boot_tty_puts( vspace[vspace_id].name ); 
327        boot_tty_puts("\n - funcs    = ");
328        boot_tty_puts( vobj[func_id].name ); 
329        boot_tty_puts( vspace[vspace_id].name ); 
330        boot_tty_puts("\n - ttys    = ");
331        boot_tty_putw( vspace[vspace_id].ttys );
332        boot_tty_puts("\n\n");
333
334        for ( vseg_id = vspace[vspace_id].vseg_offset ; 
335              vseg_id < (vspace[vspace_id].vseg_offset + vspace[vspace_id].vsegs) ; 
336              vseg_id++ )
337        {
338            boot_tty_puts("    private vseg ");
339            boot_tty_putw( vseg_id );
340
341            boot_tty_puts("\n    - name   = ");
342            boot_tty_puts( vseg[vseg_id].name );
343            boot_tty_puts("\n    - vbase  = ");
344            boot_tty_putw( vseg[vseg_id].vbase );
345            boot_tty_puts("\n    - length = ");
346            boot_tty_putw( vseg[vseg_id].length );
347            boot_tty_puts("\n    - mode   = ");
348            boot_tty_putw( vseg[vseg_id].mode );
349            boot_tty_puts("\n    - ident = ");
350            boot_tty_putw( vseg[vseg_id].ident );
351            boot_tty_puts("\n    - psegname = ");
352            boot_tty_puts( pseg[vseg[vseg_id].psegid].name );
353            boot_tty_puts("\n");
354            for ( vobj_id = vseg[vseg_id].vobj_offset ; vobj_id < vseg[vseg_id].vobj_offset + vseg[vseg_id].vobjs ; vobj_id++ )
355            {
356                boot_tty_puts("\t\t vobjs     = ");
357                                boot_tty_putw(     vobj[vobj_id].name);
358                                boot_tty_puts("\n");
359                boot_tty_puts("\t\t name     = ");
360                                boot_tty_putw(     vobj[vobj_id].name);
361                                boot_tty_puts("\n");
362                boot_tty_puts("\t\t type     = ");
363                                boot_tty_putw( vobj[vobj_id].type);
364                                boot_tty_puts("\n");
365                boot_tty_puts("\t\t length   = ");
366                                boot_tty_putw(   vobj[vobj_id].length);
367                                boot_tty_puts("\n");
368                boot_tty_puts("\t\t align    = ");
369                                boot_tty_putw(   vobj[vobj_id].align);
370                                boot_tty_puts("\n");
371                boot_tty_puts("\t\t binpath  = ");
372                                boot_tty_putw(   vobj[vobj_id].binpath);
373                                boot_tty_puts("\n");
374            }
375        }
376
377        for ( task_id = vspace[vspace_id].vseg_offset ; 
378              task_id < (vspace[vspace_id].task_offset + vspace[vspace_id].tasks) ; 
379              task_id++ )
380        {
381            boot_tty_puts("     task");
382            boot_tty_putw( task_id );
383
384            boot_tty_puts("\n     - name = ");
385            boot_tty_puts( task[task_id].name );
386            boot_tty_puts("\n     - clusterid = ");
387            boot_tty_putw( task[task_id].clusterid );
388            boot_tty_puts("\n     - proclocid = ");
389            boot_tty_putw( task[task_id].proclocid );
390            boot_tty_puts("\n     - vobjlocid = ");
391            boot_tty_putw( task[task_id].vobjlocid );
392            boot_tty_puts("\n     - startid   = ");
393            boot_tty_putw( task[task_id].startid );
394            boot_tty_puts("\n     - ttylocid  = ");
395            boot_tty_putw( task[task_id].ttylocid );
396            boot_tty_puts("\n\n");
397        }
398    }
399} // end boot_print_mapping_info()
400#endif
401
402//////////////////////////////////////////////////////////////////////////////
403// boot_pseg_get()
404// This function returns the pointer on a physical segment
405// identified  by the segment index.
406//////////////////////////////////////////////////////////////////////////////
407mapping_pseg_t* boot_pseg_get( unsigned int seg_id)
408{
409    mapping_header_t* header = (mapping_header_t*)&seg_mapping_base;
410    mapping_pseg_t*   pseg   = boot_get_pseg_base( header );
411
412    // checking argument
413    if ( seg_id >= header->psegs )
414    {
415        boot_tty_puts("\n[BOOT ERROR] : seg_id argument too large\n");
416        boot_tty_puts("               in function boot_pseg_get()\n");
417        boot_exit();
418    }
419
420    return &pseg[seg_id];                                   
421} // end boot_pseg_get()
422
423
424//////////////////////////////////////////////////////////////////////////////
425// boot_add_pte()
426// This function registers a new PTE in the page table pointed
427// by the vspace_id argument, and updates both PT1 and PT2.
428// A new PT2 is used when required.
429// As the set of PT2s is implemented as a fixed size array (no dynamic
430// allocation), this function checks a possible overflow of the PT2 array.
431//
432// The parametre global is a boolean taht indicate wether a global vseg is
433// being mapped.
434//////////////////////////////////////////////////////////////////////////////
435void boot_add_pte( unsigned int    vspace_id,   
436                   unsigned int    vpn,           
437                   unsigned int    flags,
438                   unsigned int    ppn,
439                   unsigned char   global )
440{
441    unsigned int    ix1;
442    unsigned int    ix2;
443    unsigned int    ptba;       // PT2 base address
444    unsigned int    pt2_id;     // PT2 index
445    unsigned int*   pt_flags;   // pointer on the pte_flags = &PT2[2*ix2]   
446    unsigned int*   pt_ppn;     // pointer on the pte_ppn   = &PT2[2*ix2+1] 
447
448    ix1 = vpn >> 9;             // 11 bits
449    ix2 = vpn  & 0x1FF;         //  9 bits
450
451       
452    unsigned int max_pte2   = _max_pte2[vspace_id];
453    if(max_pte2 == 0)
454    {
455        boot_tty_puts("Unfound page table for vspace ");
456        boot_tty_putw(vspace_id);
457        boot_tty_puts("\n");
458        boot_exit();
459    }
460
461    page_table_t* pt    = (page_table_t *)_ptabs[vspace_id];
462    if ( (pt->pt1[ix1] & PTE_V) == 0 )   // set a new PTD in PT1
463    {
464        pt2_id = _next_free_pt2[vspace_id];
465        if ( pt2_id == max_pte2 )
466        {
467            boot_tty_puts("\n[BOOT ERROR] in boot_add_pte() function\n");
468            boot_tty_puts("the length of the ptab vobj is too small\n"); 
469            boot_exit();
470        }
471        else
472        {
473            ptba = (unsigned int)pt + PT1_SIZE + PT2_SIZE*pt2_id;
474            pt->pt1[ix1] = PTE_V | PTE_T | (ptba >> 12);   
475            _next_free_pt2[vspace_id] = pt2_id + 1;
476        }
477    }
478    else
479    {
480        ptba = pt->pt1[ix1] << 12;
481    }
482
483    // set PTE2 after checking double mapping error
484    pt_flags = (unsigned int*)(ptba + 8*ix2);
485    pt_ppn   = (unsigned int*)(ptba + 8*ix2 + 4);
486
487    if ( ( *pt_flags & PTE_V) != 0 )    // page already mapped
488    {
489        if(global)
490        {
491            boot_tty_puts("\n[BOOT ERROR] in boot_add_pte() function\n");
492            boot_tty_puts("page already mapped\n");
493            boot_exit();
494        }else
495        {
496            /**
497             * The case where a global vseg is already mapped as private vseg of a
498             * vspace_id. Typically used when a vseg is being replicated.
499             */ 
500            boot_tty_puts("\n[BOOT] global PTE for vspace ");
501            boot_tty_putw(vspace_id);
502            boot_tty_puts(" already mapped, vpn = ");
503            boot_tty_putw(vpn);
504            boot_tty_puts("\n");
505            return;
506        }
507    }
508
509    // set PTE2
510    *pt_flags = flags;
511    *pt_ppn   = ppn;
512
513} // end boot_add_pte()
514               
515/////////////////////////////////////////////////////////////////////
516// This function build the page table for a given vspace.
517// The physical base addresses for all vsegs (global and private)
518// must have been previously computed.
519// It initializes the MWMR channels.
520/////////////////////////////////////////////////////////////////////
521void boot_vspace_pt_build( unsigned int vspace_id )
522{
523    unsigned int    vseg_id;
524    unsigned int    npages;
525    unsigned int    ppn;
526    unsigned int    vpn;
527    unsigned int    flags;
528    unsigned int    page_id;
529
530    mapping_header_t*  header = (mapping_header_t*)&seg_mapping_base; 
531    mapping_vspace_t*  vspace = boot_get_vspace_base( header );
532    mapping_vseg_t*    vseg   = boot_get_vseg_base( header );
533   
534    // private segments
535    for ( vseg_id = vspace[vspace_id].vseg_offset ; 
536          vseg_id < (vspace[vspace_id].vseg_offset + vspace[vspace_id].vsegs) ; 
537          vseg_id++ )
538    {
539        vpn       = vseg[vseg_id].vbase >> 12;
540        ppn       = vseg[vseg_id].pbase >> 12;
541        npages    = vseg[vseg_id].length >> 12;
542        if ( (vseg[vseg_id].length & 0xFFF) != 0 ) npages++;
543
544        flags = PTE_V;
545        if ( vseg[vseg_id].mode & C_MODE_MASK )  flags = flags | PTE_C;
546        if ( vseg[vseg_id].mode & X_MODE_MASK )  flags = flags | PTE_X;
547        if ( vseg[vseg_id].mode & W_MODE_MASK )  flags = flags | PTE_W;
548        if ( vseg[vseg_id].mode & U_MODE_MASK )  flags = flags | PTE_U;
549
550#if BOOT_DEBUG_PT
551boot_tty_puts("- vseg ");
552boot_tty_puts( vseg[vseg_id].name );
553boot_tty_puts(" / flags = ");
554boot_tty_putw( flags );
555boot_tty_puts("\n");
556#endif       
557        // loop on 4K pages
558        for ( page_id = 0 ; page_id < npages ; page_id++ )
559        {
560            boot_add_pte( vspace_id,
561                          vpn,
562                          flags,
563                          ppn,
564                          0 );
565            vpn++;
566            ppn++;
567        }
568    }
569
570    // global segments
571    for ( vseg_id = 0 ; vseg_id < header->globals ; vseg_id++ )
572    {
573        vpn       = vseg[vseg_id].vbase >> 12;
574        ppn       = vseg[vseg_id].pbase >> 12;
575        npages    = vseg[vseg_id].length >> 12;
576        if ( (vseg[vseg_id].length & 0xFFF) != 0 ) npages++;
577
578        flags = PTE_V;
579        if ( vseg[vseg_id].mode & C_MODE_MASK )  flags = flags | PTE_C;
580        if ( vseg[vseg_id].mode & X_MODE_MASK )  flags = flags | PTE_X;
581        if ( vseg[vseg_id].mode & W_MODE_MASK )  flags = flags | PTE_W;
582        if ( vseg[vseg_id].mode & U_MODE_MASK )  flags = flags | PTE_U;
583
584#if BOOT_DEBUG_PT
585boot_tty_puts("- vseg ");
586boot_tty_puts( vseg[vseg_id].name );
587boot_tty_puts(" / flags = ");
588boot_tty_putw( flags );
589boot_tty_puts(" / npages = ");
590boot_tty_putw( npages );
591boot_tty_puts("\n");
592#endif       
593        // loop on 4K pages
594        for ( page_id = 0 ; page_id < npages ; page_id++ )
595        {
596            boot_add_pte( vspace_id,
597                          vpn,
598                          flags,
599                          ppn,
600                          1 );
601            vpn++;
602            ppn++;
603        }
604    }
605
606} // end boot_vspace_pt_build()
607
608
609///////////////////////////////////////////////////////////////////////////
610// Align the value "toAlign" to the required alignement indicated by
611// alignPow2 ( the logarithme of 2 the alignement).
612///////////////////////////////////////////////////////////////////////////
613unsigned int align_to( unsigned toAlign, unsigned alignPow2)
614{
615    unsigned mask = (1 << alignPow2) - 1;
616    return ((toAlign + mask ) & ~mask );//page aligned
617}
618
619///////////////////////////////////////////////////////////////////////////
620// Initialise vobjs
621// For now only one type is initialised the: PTAB
622//
623// param:
624//  vobj: the vobj to initialise
625//  region_id: the vspace in wich the vobj is located or the global space(-1).
626///////////////////////////////////////////////////////////////////////////
627void initailise_vobj(mapping_vobj_t* vobj, unsigned int region_id)
628{
629    if(vobj->type == PTAB)
630    {
631        if(region_id == ((unsigned int) -1))
632        {
633            boot_tty_puts( "No PTAB vobjs are allowed in the global region" );
634            boot_exit();
635        }
636        if(vobj->length < (PT1_SIZE + PT2_SIZE) ) //at least one pt2 => ( max_pt2 >= 1)
637        {
638            boot_tty_puts("PTAB too small, minumum size is ");
639            boot_tty_putw( PT1_SIZE + PT2_SIZE);
640            boot_exit();
641        }
642
643        _ptabs[region_id]        = (page_table_t*) vobj->paddr;
644        _max_pte2[region_id]    = (vobj->length - PT1_SIZE) / PT2_SIZE;
645
646#if BOOT_DEBUG_VIEW
647        boot_tty_puts("ptabs for vspace ");
648        boot_tty_putw(region_id);
649        boot_tty_puts(" address: ");
650        boot_tty_putw((unsigned)_ptabs[region_id]);
651        boot_tty_puts("\n");
652#endif
653    } 
654}
655
656///////////////////////////////////////////////////////////////////////////
657// This function compute the physical base address for a vseg
658// as specified in the mapping info data structure.
659// It updates the pbase field of the vseg.
660// It updates the page allocator (nextfreepage field of the pseg),
661// and checks a possible pseg overflow.
662// region_id: the vspace in wich the vseg is located or the global space(-1).
663///////////////////////////////////////////////////////////////////////////
664void boot_vseg_map( mapping_vseg_t* vseg, unsigned int region_id ) 
665{
666    unsigned pages;
667    unsigned vobj_id;
668    unsigned cur_vaddr;
669    unsigned cur_paddr;
670    mapping_header_t*   header = (mapping_header_t*)&seg_mapping_base; 
671    mapping_vobj_t*     vobj   = boot_get_vobj_base( header );
672 
673    // get physical segment pointer
674    mapping_pseg_t*  pseg = boot_pseg_get( vseg->psegid );
675
676    // compute physical base address
677    if ( vseg->ident != 0 )            // identity mapping required
678    {
679        // check physical segment overflow 
680        if ( (vseg->vbase < pseg->base) || 
681             ((vseg->vbase + vseg->length) > (pseg->base + pseg->length)) )
682        {
683            boot_tty_puts("\n[BOOT ERROR] in boot_vseg_map() function\n");
684            boot_tty_puts("impossible identity mapping for virtual segment: ");
685            boot_tty_puts( vseg->name ); 
686            boot_tty_puts("\n"); 
687            boot_exit();
688        }
689        vseg->pbase = vseg->vbase;
690    }
691    else                                // unconstrained mapping
692    {
693        // check physical segment overflow
694        if ( (vseg->vbase + vseg->length) > (pseg->base + pseg->length) )
695        {
696            boot_tty_puts("\n[BOOT ERROR] in boot_vseg_map() function\n");
697            boot_tty_puts("physical segment ");
698            boot_tty_puts( pseg->name ); 
699            boot_tty_puts(" is too small to map virtual segment");
700            boot_tty_puts( vseg->name ); 
701            boot_tty_puts("\n");
702            boot_exit();
703        }
704        vseg->pbase = pseg->base + (pseg->next_free_page<<12);
705    }
706   
707
708    //loop on vobj:
709    // + to computes the length of the current vseg
710    // + Align vobjs
711    // + Initialise the vobj
712    cur_vaddr = vseg->vbase;
713    cur_paddr = vseg->pbase;
714    for(vobj_id= vseg->vobj_offset; vobj_id < (vseg->vobj_offset + vseg->vobjs); vobj_id++)
715    {
716        if(vobj[vobj_id].align)
717        {
718            cur_paddr = align_to(cur_paddr, vobj[vobj_id].align);
719        }
720
721        //set vaddr/paddr
722        vobj[vobj_id].vaddr = cur_vaddr;       
723        vobj[vobj_id].paddr = cur_paddr; 
724     
725        //set next vaddr/paddr
726        cur_vaddr += vobj[vobj_id].length;
727        cur_paddr += vobj[vobj_id].length; 
728        initailise_vobj(&vobj[vobj_id], region_id);
729    } 
730   
731    //set the length
732    vseg->length = align_to((cur_paddr - vseg->pbase), 12);
733
734    // computes number of pages
735    pages = vseg->length >> 12;
736    if ( (vseg->length & 0xFFF) != 0 ) pages++;
737
738    // set the next free physical address
739    if ( vseg->ident != 0 )
740            ;            // nothing to do
741    else                               
742        pseg->next_free_page = pseg->next_free_page + pages;
743
744#if BOOT_DEBUG_PT
745boot_tty_puts("- vseg ");
746boot_tty_puts( vseg->name );
747boot_tty_puts(" : vbase = ");
748boot_tty_putw( vseg->vbase );
749boot_tty_puts(" / pbase = ");
750boot_tty_putw( vseg->pbase );
751boot_tty_puts("\n");
752#endif 
753
754} // end boot_vseg_map()
755
756/////////////////////////////////////////////////////////////////////
757// This function cheks the mapping_info data structure
758/////////////////////////////////////////////////////////////////////
759void boot_check_mapping()
760{
761    mapping_header_t*   header = (mapping_header_t*)&seg_mapping_base; 
762
763    // checking mapping availability
764    if ( header->signature != IN_MAPPING_SIGNATURE )
765    {
766        boot_tty_puts("\n[BOOT ERROR] Illegal mapping signature: ");
767        boot_tty_putw(header->signature);
768        boot_tty_puts("\n");
769        boot_exit();
770    }
771
772#if BOOT_DEBUG_VIEW
773boot_print_mapping_info();
774#endif
775
776    // checking double definition of NB_CLUSTERS
777    if ( header->clusters != NB_CLUSTERS )
778    {
779        boot_tty_puts("\n[BOOT ERROR] Incoherent NB_CLUSTERS");
780        boot_tty_puts("\n             - In giet_config,  value = ");
781        boot_tty_putw ( NB_CLUSTERS );
782        boot_tty_puts("\n             - In mapping_info, value = ");
783        boot_tty_putw ( header->clusters );
784        boot_tty_puts("\n");
785        boot_exit();
786    }
787
788    // checking double definition of NB_TTYS
789    if ( header->ttys != NB_TTYS )
790    {
791        boot_tty_puts("\n[BOOT ERROR] Incoherent NB_TTYS");
792        boot_tty_puts("\n             - In giet_config,  value = ");
793        boot_tty_putw ( NB_TTYS );
794        boot_tty_puts("\n             - In mapping_info, value = ");
795        boot_tty_putw ( header->ttys );
796        boot_tty_puts("\n");
797        boot_exit();
798    }
799
800    // number of virtual spaces no larger than GIET_NB_VSPACE_MAX
801    if ( header->vspaces > GIET_NB_VSPACE_MAX )
802    {
803        boot_tty_puts("\n[BOOT ERROR] : number of vspaces > GIET_NB_VSPACE_MAX\n");
804        boot_tty_puts("\n");
805        boot_exit();
806    }
807} // end boot_check_mapping()
808
809/////////////////////////////////////////////////////////////////////
810// This function builds the page tables for all virtual spaces
811// defined in the mapping_info data structure.
812// For each virtual space, it maps both the global virtual segments
813// (replicated in all vspaces), and the private virtuals segments.
814/////////////////////////////////////////////////////////////////////
815void boot_pt_init()
816{
817    mapping_header_t*   header = (mapping_header_t*)&seg_mapping_base; 
818
819    mapping_vspace_t*   vspace = boot_get_vspace_base( header );     
820    mapping_pseg_t*     pseg   = boot_get_pseg_base( header ); 
821    mapping_vseg_t*     vseg   = boot_get_vseg_base( header );
822
823    unsigned int        vspace_id; 
824    unsigned int        vseg_id;
825    unsigned int        pseg_id;
826
827    // first loop on virtual spaces to map global vsegs
828
829#if BOOT_DEBUG_PT
830boot_tty_puts("\n******* mapping global vsegs ********");
831#endif
832           
833    // physical page allocators must be initialised ???
834    for ( pseg_id = 0 ; pseg_id < header->psegs ; pseg_id++ )
835    {
836        pseg[pseg_id].next_free_page = 0;
837    }
838
839    for ( vseg_id = 0 ; vseg_id < header->globals ; vseg_id++ )
840    {
841        boot_vseg_map( &vseg[vseg_id], ((unsigned int)(-1)) );
842    }
843
844    // loop on virtual vspaces to map private vsegs
845    for ( vspace_id = 0 ; vspace_id < header->vspaces ; vspace_id++ )
846    {
847
848#if BOOT_DEBUG_PT
849boot_tty_puts("\n******* mapping private vsegs in vspace ");
850boot_tty_puts(vspace[vspace_id].name);
851boot_tty_puts(" ********\n");
852#endif
853           
854        for ( vseg_id = vspace[vspace_id].vseg_offset ; 
855              vseg_id < (vspace[vspace_id].vseg_offset + vspace[vspace_id].vsegs) ; 
856              vseg_id++ )
857        {
858            boot_vseg_map( &vseg[vseg_id], vspace_id ); 
859        }
860    } 
861
862    // loop on the vspaces to build the page tables
863    for ( vspace_id = 0 ; vspace_id < header->vspaces ; vspace_id++ )
864    {
865
866#if BOOT_DEBUG_PT
867boot_tty_puts("\n******* building page table for vspace ");
868boot_tty_puts(vspace[vspace_id].name);
869boot_tty_puts(" ********\n");
870#endif
871           
872        boot_vspace_pt_build( vspace_id );
873    } 
874} // end boot_pt_init()
875
876
877
878////////////////////////////////////////////////////////////////////////////////////
879// boot_init()
880// This function is executed by one single processor to initialize the page
881// tables, the tasks contexts and the peripherals, for all applications.
882////////////////////////////////////////////////////////////////////////////////////
883void boot_init()
884{
885    // checking mapping_info
886    boot_check_mapping();
887
888    // building page tables
889    boot_pt_init();
890    boot_tty_puts("\n[BOOT] Page Tables completed at cycle ");
891    boot_tty_putw( boot_time() );
892    boot_tty_puts("\n");
893
894} // end boot_init()
895
896// Local Variables:
897// tab-width: 4
898// c-basic-offset: 4
899// c-file-offsets:((innamespace . 0)(inline-open . 0))
900// indent-tabs-mode: nil
901// End:
902// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
903
Note: See TracBrowser for help on using the repository browser.