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

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

removing the parametre variable PTE2_MAX from giet_config.
Now we compute dynamically the second table size from the length of the vobj.

File size: 31.2 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// computed using the length of the vobj and stored in the _max_pte2 global variable,
34// which is table indexed by the vspace_id.
35//
36// Each page table (one page table per virtual space) is monolithic, and
37// contains one PT1 and ((vobj.length - PT1_SIZE) / PT2_SIZE ) PT2s.
38// The PT1 is addressed using the ix1 field (11 bits) of the VPN, and
39// the selected PT2 is addressed using the ix2 field (9 bits).
40// - PT1[2048] : a first 8K aligned array of unsigned int, indexed by the (ix1) field of VPN.
41//   Each entry in the PT1 contains a 32 bits PTD. The MSB bit PTD[31] is
42//   the PTD valid bit, and LSB bits PTD[19:0] are the 20 MSB bits of the physical base
43//   address of the selected PT2.
44//   The PT1 contains 2048 PTD of 4 bytes => 8K bytes.
45// - PT2[_max_pte2[vspace_id]][1024]: an array of array of unsigned int.
46//   Each PT2[1024] must be 4K aligned,  and each entry in a PT2 contains two unsigned int:
47//   the first word contains the protection flags, and the second word contains the PPN.
48//   Each PT2 contains 512 PTE2 of 8bytes => 4K bytes.
49// The total size of a page table is finally = 8K + (GIET_NB_PT2_MAX)*4K bytes.
50////////////////////////////////////////////////////////////////////////////////////
51
52#include "../sys/mips32_registers.h"
53#include <boot_handler.h>
54#include <giet_config.h>
55#include <mapping_info.h>
56#include <mwmr_channel.h>
57
58#include <stdarg.h>
59
60#if !defined(GIET_NB_VSPACE_MAX)
61# error The GIET_NB_VSPACE_MAX value must be defined in the 'giet_config.h' file !
62#endif
63
64////////////////////////////////////////////////////////////////////////////
65//  Page Tables global variables
66////////////////////////////////////////////////////////////////////////////
67
68// Next free PT2 index array
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 array
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_puts()
110// (it uses TTY0)
111////////////////////////////////////////////////////////////////////////////
112void boot_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_putw()
127// (it uses TTY0)
128////////////////////////////////////////////////////////////////////////////
129void boot_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_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_puts("mapping_info");
225
226    boot_puts("\n - signature = ");
227    boot_putw(header->signature);
228    boot_puts("\n - name      = ");
229    boot_puts(header->name);
230    boot_puts("\n - clusters  = ");
231    boot_putw(header->clusters);
232    boot_puts("\n - psegs     = ");
233    boot_putw(header->psegs);
234    boot_puts("\n - ttys      = ");
235    boot_putw(header->ttys);
236    boot_puts("\n - fbs       = ");
237    boot_putw(header->fbs);
238    boot_puts("\n - vspaces   = ");
239    boot_putw(header->vspaces);
240    boot_puts("\n - globals   = ");
241    boot_putw(header->globals);
242    boot_puts("\n - vsegs     = ");
243    boot_putw(header->vsegs);
244    boot_puts("\n - vobjs     = ");
245    boot_putw(header->vobjs);
246    boot_puts("\n - tasks     = ");
247    boot_putw(header->tasks);
248    boot_puts("\n\n");
249
250    // clusters
251    for ( cluster_id = 0 ; cluster_id < header->clusters ; cluster_id++ )
252    {
253        boot_puts("cluster ");
254        boot_putw(cluster_id);
255
256        boot_puts("\n - procs  = ");
257        boot_putw(cluster[cluster_id].procs);
258        boot_puts("\n\n");
259    }
260
261    // psegs
262    for ( pseg_id = 0 ; pseg_id < header->psegs ; pseg_id++ )
263    {
264        boot_puts("pseg ");
265        boot_putw(pseg_id);
266
267        boot_puts("\n - name   = ");
268        boot_puts( pseg[pseg_id].name );
269        boot_puts("\n - base   = ");
270        boot_putw( pseg[pseg_id].base );
271        boot_puts("\n - length = ");
272        boot_putw( pseg[pseg_id].length );
273        boot_puts("\n\n");
274    }
275
276    // globals
277    for ( vseg_id = 0 ; vseg_id < header->globals ; vseg_id++ )
278    {
279        boot_puts("global vseg ");
280        boot_putw(vseg_id);
281
282        boot_puts("\n - name        = ");
283        boot_puts( vseg[vseg_id].name );
284        boot_puts("\n - vbase       = ");
285        boot_putw( vseg[vseg_id].vbase );
286        boot_puts("\n - length      = ");
287        boot_putw( vseg[vseg_id].length );
288        boot_puts("\n - mode        = ");
289        boot_putw( vseg[vseg_id].mode );
290        boot_puts("\n - ident       = ");
291        boot_putw( vseg[vseg_id].ident );
292        boot_puts("\n - psegname    = ");
293        boot_puts( pseg[vseg[vseg_id].psegid].name );
294        boot_puts("\n - vobjs       = ");
295        boot_putw( vseg[vseg_id].vobjs );
296        boot_puts("\n - vobj_offset = ");
297        boot_putw( vseg[vseg_id].vobj_offset );
298        boot_puts("\n");
299        for ( vobj_id = vseg[vseg_id].vobj_offset ; 
300              vobj_id < vseg[vseg_id].vobj_offset + vseg[vseg_id].vobjs ; 
301              vobj_id++ )
302        {
303                        boot_puts("\n\t vobj ");
304            boot_puts( vobj[vobj_id].name);
305            boot_puts("\n\t type     = ");
306                        boot_putw( vobj[vobj_id].type);
307            boot_puts("\n\t length   = ");
308                        boot_putw(   vobj[vobj_id].length);
309            boot_puts("\n\t align    = ");
310                        boot_putw(   vobj[vobj_id].align);
311            boot_puts("\n\t binpath  = ");
312                        boot_puts(   vobj[vobj_id].binpath);
313                        boot_puts("\n\n");
314        }
315    }
316
317    // vspaces
318    for ( vspace_id = 0 ; vspace_id < header->vspaces ; vspace_id++ )
319    {
320        unsigned int start_id = vspace[vspace_id].vobj_offset + 
321                                vspace[vspace_id].start_offset; 
322
323        boot_puts("vspace ");
324        boot_putw(vspace_id);
325
326        boot_puts("\n - name        = ");
327        boot_puts( vspace[vspace_id].name ); 
328        boot_puts("\n - start_vobj  = ");
329        boot_puts( vobj[start_id].name ); 
330        boot_puts("\n - vsegs       = ");
331        boot_putw( vspace[vspace_id].vsegs ); 
332        boot_puts("\n - vobjs       = ");
333        boot_putw( vspace[vspace_id].vobjs ); 
334        boot_puts("\n - tasks       = ");
335        boot_putw( vspace[vspace_id].tasks ); 
336        boot_puts("\n - vseg_offset = ");
337        boot_putw( vspace[vspace_id].vseg_offset ); 
338        boot_puts("\n - vobj_offset = ");
339        boot_putw( vspace[vspace_id].vobj_offset ); 
340        boot_puts("\n - task_offset = ");
341        boot_putw( vspace[vspace_id].task_offset ); 
342        boot_puts("\n\n");
343
344        for ( vseg_id = vspace[vspace_id].vseg_offset ; 
345              vseg_id < (vspace[vspace_id].vseg_offset + vspace[vspace_id].vsegs) ; 
346              vseg_id++ )
347        {
348            boot_puts("    private vseg ");
349            boot_putw( vseg_id );
350
351            boot_puts("\n    - name        = ");
352            boot_puts( vseg[vseg_id].name );
353            boot_puts("\n    - vbase       = ");
354            boot_putw( vseg[vseg_id].vbase );
355            boot_puts("\n    - length      = ");
356            boot_putw( vseg[vseg_id].length );
357            boot_puts("\n    - mode        = ");
358            boot_putw( vseg[vseg_id].mode );
359            boot_puts("\n    - ident       = ");
360            boot_putw( vseg[vseg_id].ident );
361            boot_puts("\n    - psegname    = ");
362            boot_puts( pseg[vseg[vseg_id].psegid].name );
363            boot_puts("\n    - vobjs       = ");
364            boot_putw( vseg[vseg_id].vobjs );
365            boot_puts("\n    - vobj_offset = ");
366            boot_putw( vseg[vseg_id].vobj_offset );
367            boot_puts("\n");
368
369            for ( vobj_id = vseg[vseg_id].vobj_offset ; 
370                  vobj_id < vseg[vseg_id].vobj_offset + vseg[vseg_id].vobjs ; 
371                  vobj_id++ )
372            {
373                boot_puts("\n\t\t vobj ");
374                boot_puts( vobj[vobj_id].name);
375                boot_puts("\n\t\t type     = ");
376                boot_putw( vobj[vobj_id].type);
377                boot_puts("\n\t\t length   = ");
378                            boot_putw(   vobj[vobj_id].length);
379                boot_puts("\n\t\t align    = ");
380                            boot_putw(   vobj[vobj_id].align);
381                boot_puts("\n\t\t binpath  = ");
382                        boot_puts(   vobj[vobj_id].binpath);
383                        boot_puts("\n\n");
384            }
385        }
386
387        for ( task_id = vspace[vspace_id].vseg_offset ; 
388              task_id < (vspace[vspace_id].task_offset + vspace[vspace_id].tasks) ; 
389              task_id++ )
390        {
391            boot_puts("     task");
392            boot_putw( task_id );
393
394            boot_puts("\n     - name = ");
395            boot_puts( task[task_id].name );
396            boot_puts("\n     - clusterid = ");
397            boot_putw( task[task_id].clusterid );
398            boot_puts("\n     - proclocid = ");
399            boot_putw( task[task_id].proclocid );
400            boot_puts("\n     - vobjlocid = ");
401            boot_putw( task[task_id].vobjlocid );
402            boot_puts("\n     - startid   = ");
403            boot_putw( task[task_id].startid );
404            boot_puts("\n     - use_tty   = ");
405            boot_putw( task[task_id].use_tty );
406            boot_puts("\n     - use_fb   = ");
407            boot_putw( task[task_id].use_fb );
408            boot_puts("\n\n");
409        }
410    }
411} // end boot_print_mapping_info()
412#endif
413
414//////////////////////////////////////////////////////////////////////////////
415// boot_pseg_get()
416// This function returns the pointer on a physical segment
417// identified  by the pseg index.
418//////////////////////////////////////////////////////////////////////////////
419mapping_pseg_t* boot_pseg_get( unsigned int seg_id)
420{
421    mapping_header_t* header = (mapping_header_t*)&seg_mapping_base;
422    mapping_pseg_t*   pseg   = boot_get_pseg_base( header );
423
424    // checking argument
425    if ( seg_id >= header->psegs )
426    {
427        boot_puts("\n[BOOT ERROR] : seg_id argument too large\n");
428        boot_puts("               in function boot_pseg_get()\n");
429        boot_exit();
430    }
431
432    return &pseg[seg_id];                                   
433} // end boot_pseg_get()
434
435//////////////////////////////////////////////////////////////////////////////
436// boot_add_pte()
437// This function registers a new PTE in the page table pointed
438// by the vspace_id argument, and updates both PT1 and PT2.
439// A new PT2 is used when required.
440// As the set of PT2s is implemented as a fixed size array (no dynamic
441// allocation), this function checks a possible overflow of the PT2 array.
442//
443// The global parameter is a boolean indicating wether a global vseg is
444// being mapped.
445//////////////////////////////////////////////////////////////////////////////
446void boot_add_pte( unsigned int    vspace_id,   
447                   unsigned int    vpn,           
448                   unsigned int    flags,
449                   unsigned int    ppn )
450{
451    unsigned int    ix1;
452    unsigned int    ix2;
453    unsigned int    ptba;       // PT2 base address
454    unsigned int    pt2_id;     // PT2 index
455    unsigned int*   pt_flags;   // pointer on the pte_flags = &PT2[2*ix2]   
456    unsigned int*   pt_ppn;     // pointer on the pte_ppn   = &PT2[2*ix2+1] 
457
458    ix1 = vpn >> 9;             // 11 bits
459    ix2 = vpn  & 0x1FF;         //  9 bits
460
461    // since the max_pte2 has to be > 1, we check that he have been set
462    // otherwise it means tha the ptabs has not been set
463    unsigned int max_pte2   = _max_pte2[vspace_id];
464    if(max_pte2 == 0)
465    {
466        boot_puts("Unfound page table for vspace ");
467        boot_putw(vspace_id);
468        boot_puts("\n");
469        boot_exit();
470    }
471
472    page_table_t* pt = (page_table_t *)_ptabs[vspace_id];
473    if ( (pt->pt1[ix1] & PTE_V) == 0 )   // set a new PTD in PT1
474    {
475        pt2_id = _next_free_pt2[vspace_id];
476        if ( pt2_id == max_pte2 )
477        {
478            boot_puts("\n[BOOT ERROR] in boot_add_pte() function\n");
479            boot_puts("the length of the ptab vobj is too small\n"); 
480            boot_exit();
481        }
482        else
483        {
484            ptba = (unsigned int)pt + PT1_SIZE + PT2_SIZE*pt2_id;
485            pt->pt1[ix1] = PTE_V | PTE_T | (ptba >> 12);   
486            _next_free_pt2[vspace_id] = pt2_id + 1;
487        }
488    }
489    else
490    {
491        ptba = pt->pt1[ix1] << 12;
492    }
493
494    // set PTE2 after checking double mapping error
495    pt_flags = (unsigned int*)(ptba + 8*ix2);
496    pt_ppn   = (unsigned int*)(ptba + 8*ix2 + 4);
497
498    if ( ( *pt_flags & PTE_V) != 0 )    // page already mapped
499    {
500        boot_puts("\n[BOOT ERROR] in boot_add_pte() function\n");
501        boot_puts("page already mapped\n");
502        boot_exit();
503    }
504
505    // set PTE2
506    *pt_flags = flags;
507    *pt_ppn   = ppn;
508
509} // end boot_add_pte()
510               
511/////////////////////////////////////////////////////////////////////
512// This function build the page table for a given vspace.
513// The physical base addresses for all vsegs (global and private)
514// must have been previously computed.
515// It initializes the MWMR channels.
516/////////////////////////////////////////////////////////////////////
517void boot_vspace_pt_build( unsigned int vspace_id )
518{
519    unsigned int    vseg_id;
520    unsigned int    npages;
521    unsigned int    ppn;
522    unsigned int    vpn;
523    unsigned int    flags;
524    unsigned int    page_id;
525
526    mapping_header_t*  header = (mapping_header_t*)&seg_mapping_base; 
527    mapping_vspace_t*  vspace = boot_get_vspace_base( header );
528    mapping_vseg_t*    vseg   = boot_get_vseg_base( header );
529   
530    // private segments
531    for ( vseg_id = vspace[vspace_id].vseg_offset ; 
532          vseg_id < (vspace[vspace_id].vseg_offset + vspace[vspace_id].vsegs) ; 
533          vseg_id++ )
534    {
535        vpn       = vseg[vseg_id].vbase >> 12;
536        ppn       = vseg[vseg_id].pbase >> 12;
537        npages    = vseg[vseg_id].length >> 12;
538        if ( (vseg[vseg_id].length & 0xFFF) != 0 ) npages++;
539
540        flags = PTE_V;
541        if ( vseg[vseg_id].mode & C_MODE_MASK )  flags = flags | PTE_C;
542        if ( vseg[vseg_id].mode & X_MODE_MASK )  flags = flags | PTE_X;
543        if ( vseg[vseg_id].mode & W_MODE_MASK )  flags = flags | PTE_W;
544        if ( vseg[vseg_id].mode & U_MODE_MASK )  flags = flags | PTE_U;
545
546#if BOOT_DEBUG_PT
547boot_puts("- vseg ");
548boot_puts( vseg[vseg_id].name );
549boot_puts(" / flags = ");
550boot_putw( flags );
551boot_puts(" / npages = ");
552boot_putw( npages );
553boot_puts("\n");
554#endif       
555        // loop on 4K pages
556        for ( page_id = 0 ; page_id < npages ; page_id++ )
557        {
558            boot_add_pte( vspace_id,
559                          vpn,
560                          flags,
561                          ppn );
562            vpn++;
563            ppn++;
564        }
565    }
566
567    // global segments
568    for ( vseg_id = 0 ; vseg_id < header->globals ; vseg_id++ )
569    {
570        vpn       = vseg[vseg_id].vbase >> 12;
571        ppn       = vseg[vseg_id].pbase >> 12;
572        npages    = vseg[vseg_id].length >> 12;
573        if ( (vseg[vseg_id].length & 0xFFF) != 0 ) npages++;
574
575        flags = PTE_V;
576        if ( vseg[vseg_id].mode & C_MODE_MASK )  flags = flags | PTE_C;
577        if ( vseg[vseg_id].mode & X_MODE_MASK )  flags = flags | PTE_X;
578        if ( vseg[vseg_id].mode & W_MODE_MASK )  flags = flags | PTE_W;
579        if ( vseg[vseg_id].mode & U_MODE_MASK )  flags = flags | PTE_U;
580
581#if BOOT_DEBUG_PT
582boot_puts("- vseg ");
583boot_puts( vseg[vseg_id].name );
584boot_puts(" / flags = ");
585boot_putw( flags );
586boot_puts(" / npages = ");
587boot_putw( npages );
588boot_puts("\n");
589#endif       
590        // loop on 4K pages
591        for ( page_id = 0 ; page_id < npages ; page_id++ )
592        {
593            boot_add_pte( vspace_id,
594                          vpn,
595                          flags,
596                          ppn );
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 and the length fields of the vseg.
619// It updates the pbase and vbase fields of all vobjs in the vseg.
620// It updates the next_base field of the pseg.
621// It checks a possible pseg overflow.
622// It is a global vseg if vspace_id = (-1)
623///////////////////////////////////////////////////////////////////////////
624void boot_vseg_map( mapping_vseg_t*     vseg, 
625                    unsigned int        vspace_id ) 
626{
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->next_base;
644
645        // test alignment constraint
646        if ( vobj[vseg->vobj_offset].align )
647        {
648            vseg->pbase = align_to( vseg->pbase, vobj[vseg->vobj_offset].align );
649        }
650    }
651   
652    // loop on vobjs to (1) computes the length of the vseg,
653    // (2) initialise the vaddr and paddr fields of all vobjs,
654    // (3) initialise the page table pointers array
655
656    cur_vaddr = vseg->vbase;
657    cur_paddr = vseg->pbase;
658
659    for( vobj_id = vseg->vobj_offset; 
660         vobj_id < (vseg->vobj_offset + vseg->vobjs); 
661         vobj_id++)
662    {
663        if ( vobj[vobj_id].align )
664        {
665            cur_paddr = align_to(cur_paddr, vobj[vobj_id].align);
666        }
667
668        // set vaddr/paddr for current vobj
669        vobj[vobj_id].vaddr = cur_vaddr;       
670        vobj[vobj_id].paddr = cur_paddr; 
671     
672        // set next vaddr/paddr
673        cur_vaddr += vobj[vobj_id].length;
674        cur_paddr += vobj[vobj_id].length; 
675
676        // initialise _ptabs[] if current vobj is a PTAB
677        if ( vobj[vobj_id].type == VOBJ_TYPE_PTAB )
678        {
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
687            if(vobj[vobj_id].length < (PT1_SIZE + PT2_SIZE) ) //at least one pte2 => ( max_pte2 >= 1)
688            {
689                boot_puts( "\n[BOOT ERROR] in boot_vseg_map() function, " );
690                boot_puts("PTAB too small, minumum size is: ");
691                boot_putw( PT1_SIZE + PT2_SIZE);
692                boot_exit();
693            }
694
695            /* getting the physical address of the ptab */
696            _ptabs[vspace_id]        = (page_table_t*) vobj[vobj_id].paddr;
697            /* computing the number of second level page */
698            _max_pte2[vspace_id]    = (vobj[vobj_id].length - PT1_SIZE) / PT2_SIZE;
699        }
700    } // end for vobjs
701   
702    //set the vseg length
703    vseg->length = align_to( (cur_paddr - vseg->pbase), 12);
704
705    // checking pseg overflow
706    if ( (vseg->pbase < pseg->base) || 
707         ((vseg->pbase + vseg->length) > (pseg->base + pseg->length)) )
708    {
709        boot_puts("\n[BOOT ERROR] in boot_vseg_map() function\n");
710        boot_puts("impossible mapping for virtual segment: ");
711        boot_puts( vseg->name ); 
712        boot_puts("\n"); 
713        boot_puts("vseg pbase = ");
714        boot_putw( vseg->pbase ); 
715        boot_puts("\n"); 
716        boot_puts("vseg length = ");
717        boot_putw( vseg->length ); 
718        boot_puts("\n"); 
719        boot_puts("pseg pbase = ");
720        boot_putw( pseg->base ); 
721        boot_puts("\n"); 
722        boot_puts("pseg length = ");
723        boot_putw( pseg->length ); 
724        boot_puts("\n"); 
725        boot_exit();
726    }
727
728    // set the next_base field in vseg
729    if ( vseg->ident == 0 )
730        pseg->next_base = vseg->pbase + vseg->length;
731
732#if BOOT_DEBUG_PT
733boot_puts( vseg->name );
734boot_puts(" : len = ");
735boot_putw( vseg->length );
736boot_puts(" / vbase = ");
737boot_putw( vseg->vbase );
738boot_puts(" / pbase = ");
739boot_putw( vseg->pbase );
740boot_puts("\n");
741#endif 
742
743} // end boot_vseg_map()
744
745/////////////////////////////////////////////////////////////////////
746// This function checks the mapping_info data structure
747/////////////////////////////////////////////////////////////////////
748void boot_check_mapping()
749{
750    mapping_header_t*   header = (mapping_header_t*)&seg_mapping_base; 
751
752    // checking mapping availability
753    if ( header->signature != IN_MAPPING_SIGNATURE )
754    {
755        boot_puts("\n[BOOT ERROR] Illegal mapping signature: ");
756        boot_putw(header->signature);
757        boot_puts("\n");
758        boot_exit();
759    }
760
761#if BOOT_DEBUG_VIEW
762boot_print_mapping_info();
763#endif
764
765    // checking double definition of NB_CLUSTERS
766    if ( header->clusters != NB_CLUSTERS )
767    {
768        boot_puts("\n[BOOT ERROR] Incoherent NB_CLUSTERS");
769        boot_puts("\n             - In giet_config,  value = ");
770        boot_putw ( NB_CLUSTERS );
771        boot_puts("\n             - In mapping_info, value = ");
772        boot_putw ( header->clusters );
773        boot_puts("\n");
774        boot_exit();
775    }
776
777    // checking double definition of NB_TTYS
778    if ( header->ttys != NB_TTYS )
779    {
780        boot_puts("\n[BOOT ERROR] Incoherent NB_TTYS");
781        boot_puts("\n             - In giet_config,  value = ");
782        boot_putw ( NB_TTYS );
783        boot_puts("\n             - In mapping_info, value = ");
784        boot_putw ( header->ttys );
785        boot_puts("\n");
786        boot_exit();
787    }
788
789    // number of virtual spaces no larger than GIET_NB_VSPACE_MAX
790    if ( header->vspaces > GIET_NB_VSPACE_MAX )
791    {
792        boot_puts("\n[BOOT ERROR] : number of vspaces > GIET_NB_VSPACE_MAX\n");
793        boot_puts("\n");
794        boot_exit();
795    }
796} // end boot_check_mapping()
797
798/////////////////////////////////////////////////////////////////////
799// This function builds the page tables for all virtual spaces
800// defined in the mapping_info data structure.
801// For each virtual space, it maps both the global virtual segments
802// (replicated in all vspaces), and the private virtuals segments.
803/////////////////////////////////////////////////////////////////////
804void boot_pt_init()
805{
806    mapping_header_t*   header = (mapping_header_t*)&seg_mapping_base; 
807
808    mapping_vspace_t*   vspace = boot_get_vspace_base( header );     
809    mapping_pseg_t*     pseg   = boot_get_pseg_base( header ); 
810    mapping_vseg_t*     vseg   = boot_get_vseg_base( header );
811
812    unsigned int        vspace_id; 
813    unsigned int        vseg_id;
814    unsigned int        pseg_id;
815
816    // checking mapping_info
817    boot_check_mapping();
818
819    // physical page allocators must be initialised
820    for ( pseg_id = 0 ; pseg_id < header->psegs ; pseg_id++ )
821    {
822        pseg[pseg_id].next_base = pseg[pseg_id].base;
823    }
824
825#if BOOT_DEBUG_PT
826boot_puts("\n******* mapping global vsegs ********\n");
827#endif
828           
829    // step 1 : first loop on virtual spaces to map global vsegs
830    for ( vseg_id = 0 ; vseg_id < header->globals ; vseg_id++ )
831    {
832        boot_vseg_map( &vseg[vseg_id], ((unsigned int)(-1)) );
833    }
834
835    // step 2 : loop on virtual vspaces to map private vsegs
836    for ( vspace_id = 0 ; vspace_id < header->vspaces ; vspace_id++ )
837    {
838
839#if BOOT_DEBUG_PT
840boot_puts("\n******* mapping private vsegs in vspace ");
841boot_puts(vspace[vspace_id].name);
842boot_puts(" ********\n");
843#endif
844           
845        for ( vseg_id = vspace[vspace_id].vseg_offset ; 
846              vseg_id < (vspace[vspace_id].vseg_offset + vspace[vspace_id].vsegs) ; 
847              vseg_id++ )
848        {
849            boot_vseg_map( &vseg[vseg_id], vspace_id ); 
850        }
851    } 
852
853    // step 3 : loop on the vspaces to build the page tables
854    for ( vspace_id = 0 ; vspace_id < header->vspaces ; vspace_id++ )
855    {
856
857#if BOOT_DEBUG_PT
858boot_puts("\n******* building page table for vspace ");
859boot_puts(vspace[vspace_id].name);
860boot_puts(" ********\n");
861#endif
862           
863        boot_vspace_pt_build( vspace_id );
864
865#if BOOT_DEBUG_PT
866boot_puts("\n>>> page table physical address = ");
867boot_putw((unsigned int)_ptabs[vspace_id]);
868boot_puts(", page table max_pte2 = ");
869boot_putw((unsigned int)_max_pte2[vspace_id]);
870boot_puts("\n");
871#endif
872    } 
873
874    boot_puts("\n[BOOT] Page Tables initialisation completed at cycle ");
875    boot_putw( boot_time() );
876    boot_puts("\n");
877
878} // end boot_pt_init()
879
880// Local Variables:
881// tab-width: 4
882// c-basic-offset: 4
883// c-file-offsets:((innamespace . 0)(inline-open . 0))
884// indent-tabs-mode: nil
885// End:
886// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
887
Note: See TracBrowser for help on using the repository browser.