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

Last change on this file since 165 was 165, checked in by alain, 12 years ago

Introducing various modifications in kernel initialisation

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