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

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

Cleaning unused files
Simplifying Makefile
adding missing include

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