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

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

Fix several bugs to use the vci_block_device with MMU activated

File size: 30.6 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 by the (GIET_NB_PT2_MAX) configuration parameter.
34// The max number of virtual spaces (GIET_NB_VSPACE_MAX) is a configuration parameter.
35//
36// Each page table (one page table per virtual space) is monolithic, and
37// contains one PT1 and (GIET_NB_PT2_MAX) PT2s. The PT1 is addressed using the ix1 field
38// (11 bits) of the VPN, and the selected PT2 is addressed using the ix2 field (9 bits).
39// - PT1[2048] : a first 8K aligned array of unsigned int, indexed by the (ix1) field of VPN.
40//   Each entry in the PT1 contains a 32 bits PTD. The MSB bit PTD[31] is
41//   the PTD valid bit, and LSB bits PTD[19:0] are the 20 MSB bits of the physical base
42//   address of the selected PT2.
43//   The PT1 contains 2048 PTD of 4 bytes => 8K bytes.
44// - PT2[1024][GIET_NB_PT2_MAX] : an array of array of unsigned int.
45//   Each PT2[1024] must be 4K aligned,  and each entry in a PT2 contains two unsigned int:
46//   the first word contains the protection flags, and the second word contains the PPN.
47//   Each PT2 contains 512 PTE2 of 8bytes => 4K bytes.
48// The total size of a page table is finally = 8K + (GIET_NB_PT2_MAX)*4K bytes.
49////////////////////////////////////////////////////////////////////////////////////
50
51#include "../sys/mips32_registers.h"
52#include <boot_handler.h>
53#include <mapping_info.h>
54#include <mwmr_channel.h>
55
56#include <stdarg.h>
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#if !defined(GIET_NB_PT2_MAX)
63# error The GIET_NB_PT2_MAX value must be defined in the 'giet_config.h' file !
64#endif
65
66////////////////////////////////////////////////////////////////////////////
67//  Page Tables global variables
68////////////////////////////////////////////////////////////////////////////
69
70// Next free PT2 index array
71unsigned int  _next_free_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 global parameter is a boolean indicating 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{
449    unsigned int    ix1;
450    unsigned int    ix2;
451    unsigned int    ptba;       // PT2 base address
452    unsigned int    pt2_id;     // PT2 index
453    unsigned int*   pt_flags;   // pointer on the pte_flags = &PT2[2*ix2]   
454    unsigned int*   pt_ppn;     // pointer on the pte_ppn   = &PT2[2*ix2+1] 
455
456    ix1 = vpn >> 9;             // 11 bits
457    ix2 = vpn  & 0x1FF;         //  9 bits
458
459    page_table_t* pt = (page_table_t *)_ptabs[vspace_id];
460    if ( (pt->pt1[ix1] & PTE_V) == 0 )   // set a new PTD in PT1
461    {
462        pt2_id = _next_free_pt2[vspace_id];
463        if ( pt2_id == GIET_NB_PT2_MAX )
464        {
465            boot_puts("\n[BOOT ERROR] in boot_add_pte() function\n");
466            boot_puts("the length of the ptab vobj is too small\n"); 
467            boot_exit();
468        }
469        else
470        {
471            ptba = (unsigned int)pt + PT1_SIZE + PT2_SIZE*pt2_id;
472            pt->pt1[ix1] = PTE_V | PTE_T | (ptba >> 12);   
473            _next_free_pt2[vspace_id] = pt2_id + 1;
474        }
475    }
476    else
477    {
478        ptba = pt->pt1[ix1] << 12;
479    }
480
481    // set PTE2 after checking double mapping error
482    pt_flags = (unsigned int*)(ptba + 8*ix2);
483    pt_ppn   = (unsigned int*)(ptba + 8*ix2 + 4);
484
485    if ( ( *pt_flags & PTE_V) != 0 )    // page already mapped
486    {
487        boot_puts("\n[BOOT ERROR] in boot_add_pte() function\n");
488        boot_puts("page already mapped\n");
489        boot_exit();
490    }
491
492    // set PTE2
493    *pt_flags = flags;
494    *pt_ppn   = ppn;
495
496} // end boot_add_pte()
497               
498/////////////////////////////////////////////////////////////////////
499// This function build the page table for a given vspace.
500// The physical base addresses for all vsegs (global and private)
501// must have been previously computed.
502// It initializes the MWMR channels.
503/////////////////////////////////////////////////////////////////////
504void boot_vspace_pt_build( unsigned int vspace_id )
505{
506    unsigned int    vseg_id;
507    unsigned int    npages;
508    unsigned int    ppn;
509    unsigned int    vpn;
510    unsigned int    flags;
511    unsigned int    page_id;
512
513    mapping_header_t*  header = (mapping_header_t*)&seg_mapping_base; 
514    mapping_vspace_t*  vspace = boot_get_vspace_base( header );
515    mapping_vseg_t*    vseg   = boot_get_vseg_base( header );
516   
517    // private segments
518    for ( vseg_id = vspace[vspace_id].vseg_offset ; 
519          vseg_id < (vspace[vspace_id].vseg_offset + vspace[vspace_id].vsegs) ; 
520          vseg_id++ )
521    {
522        vpn       = vseg[vseg_id].vbase >> 12;
523        ppn       = vseg[vseg_id].pbase >> 12;
524        npages    = vseg[vseg_id].length >> 12;
525        if ( (vseg[vseg_id].length & 0xFFF) != 0 ) npages++;
526
527        flags = PTE_V;
528        if ( vseg[vseg_id].mode & C_MODE_MASK )  flags = flags | PTE_C;
529        if ( vseg[vseg_id].mode & X_MODE_MASK )  flags = flags | PTE_X;
530        if ( vseg[vseg_id].mode & W_MODE_MASK )  flags = flags | PTE_W;
531        if ( vseg[vseg_id].mode & U_MODE_MASK )  flags = flags | PTE_U;
532
533#if BOOT_DEBUG_PT
534boot_puts("- vseg ");
535boot_puts( vseg[vseg_id].name );
536boot_puts(" / flags = ");
537boot_putw( flags );
538boot_puts(" / npages = ");
539boot_putw( npages );
540boot_puts("\n");
541#endif       
542        // loop on 4K pages
543        for ( page_id = 0 ; page_id < npages ; page_id++ )
544        {
545            boot_add_pte( vspace_id,
546                          vpn,
547                          flags,
548                          ppn );
549            vpn++;
550            ppn++;
551        }
552    }
553
554    // global segments
555    for ( vseg_id = 0 ; vseg_id < header->globals ; vseg_id++ )
556    {
557        vpn       = vseg[vseg_id].vbase >> 12;
558        ppn       = vseg[vseg_id].pbase >> 12;
559        npages    = vseg[vseg_id].length >> 12;
560        if ( (vseg[vseg_id].length & 0xFFF) != 0 ) npages++;
561
562        flags = PTE_V;
563        if ( vseg[vseg_id].mode & C_MODE_MASK )  flags = flags | PTE_C;
564        if ( vseg[vseg_id].mode & X_MODE_MASK )  flags = flags | PTE_X;
565        if ( vseg[vseg_id].mode & W_MODE_MASK )  flags = flags | PTE_W;
566        if ( vseg[vseg_id].mode & U_MODE_MASK )  flags = flags | PTE_U;
567
568#if BOOT_DEBUG_PT
569boot_puts("- vseg ");
570boot_puts( vseg[vseg_id].name );
571boot_puts(" / flags = ");
572boot_putw( flags );
573boot_puts(" / npages = ");
574boot_putw( npages );
575boot_puts("\n");
576#endif       
577        // loop on 4K pages
578        for ( page_id = 0 ; page_id < npages ; page_id++ )
579        {
580            boot_add_pte( vspace_id,
581                          vpn,
582                          flags,
583                          ppn );
584            vpn++;
585            ppn++;
586        }
587    }
588
589} // end boot_vspace_pt_build()
590
591///////////////////////////////////////////////////////////////////////////
592// Align the value "toAlign" to the required alignement indicated by
593// alignPow2 ( the logarithme of 2 the alignement).
594///////////////////////////////////////////////////////////////////////////
595unsigned int align_to( unsigned int toAlign, 
596                       unsigned int alignPow2)
597{
598    unsigned int    mask = (1 << alignPow2) - 1;
599    return ((toAlign + mask ) & ~mask ); 
600}
601
602///////////////////////////////////////////////////////////////////////////
603// This function compute the physical base address for a vseg
604// as specified in the mapping info data structure.
605// It updates the pbase and the length fields of the vseg.
606// It updates the pbase and vbase fields of all vobjs in the vseg.
607// It updates the next_base field of the pseg.
608// It checks a possible pseg overflow.
609// It is a global vseg if vspace_id = (-1)
610///////////////////////////////////////////////////////////////////////////
611void boot_vseg_map( mapping_vseg_t*     vseg, 
612                    unsigned int        vspace_id ) 
613{
614    unsigned int        pages;
615    unsigned int        vobj_id;
616    unsigned int        cur_vaddr;
617    unsigned int        cur_paddr;
618    mapping_header_t*   header = (mapping_header_t*)&seg_mapping_base; 
619    mapping_vobj_t*     vobj   = boot_get_vobj_base( header );
620 
621    // get physical segment pointer
622    mapping_pseg_t*  pseg = boot_pseg_get( vseg->psegid );
623
624    // compute physical base address
625    if ( vseg->ident != 0 )            // identity mapping required
626    {
627         vseg->pbase = vseg->vbase;
628    }
629    else                                // unconstrained mapping
630    {
631        vseg->pbase = pseg->next_base;
632
633        // test alignment constraint
634        if ( vobj[vseg->vobj_offset].align )
635        {
636            vseg->pbase = align_to( vseg->pbase, vobj[vseg->vobj_offset].align );
637        }
638    }
639   
640    // loop on vobjs to (1) computes the length of the vseg,
641    // (2) initialise the vaddr and paddr fields of all vobjs,
642    // (3) initialise the page table pointers array
643
644    cur_vaddr = vseg->vbase;
645    cur_paddr = vseg->pbase;
646
647    for( vobj_id = vseg->vobj_offset; 
648         vobj_id < (vseg->vobj_offset + vseg->vobjs); 
649         vobj_id++)
650    {
651        if ( vobj[vobj_id].align )
652        {
653            cur_paddr = align_to(cur_paddr, vobj[vobj_id].align);
654        }
655
656        // set vaddr/paddr for current vobj
657        vobj[vobj_id].vaddr = cur_vaddr;       
658        vobj[vobj_id].paddr = cur_paddr; 
659     
660        // set next vaddr/paddr
661        cur_vaddr += vobj[vobj_id].length;
662        cur_paddr += vobj[vobj_id].length; 
663
664        // initialise _ptabs[] if current vobj is a PTAB
665        if ( vobj[vobj_id].type == VOBJ_TYPE_PTAB )
666        {
667            if(vobj[vobj_id].length < (PT1_SIZE + PT2_SIZE*GIET_NB_PT2_MAX) ) 
668            {
669                boot_puts( "\n[BOOT ERROR] in boot_vseg_map() function: " );
670                boot_puts("PTAB vobj is too small in vspace ");
671                boot_putw(vspace_id);
672                boot_puts("\n");
673                boot_exit();
674            }
675            if(vspace_id == ((unsigned int) -1))    // global vseg
676            {
677                boot_puts( "\n[BOOT ERROR] in boot_vseg_map() function: " );
678                boot_puts( "a PTAB vobj cannot be global" );
679                boot_exit();
680            }
681            _ptabs[vspace_id] = (page_table_t*)vobj[vobj_id].paddr;
682        }
683    } // end for vobjs
684   
685    //set the vseg length
686    vseg->length = align_to( (cur_paddr - vseg->pbase), 12);
687
688    // checking pseg overflow
689    if ( (vseg->pbase < pseg->base) || 
690         ((vseg->pbase + vseg->length) > (pseg->base + pseg->length)) )
691    {
692        boot_puts("\n[BOOT ERROR] in boot_vseg_map() function\n");
693        boot_puts("impossible mapping for virtual segment: ");
694        boot_puts( vseg->name ); 
695        boot_puts("\n"); 
696        boot_puts("vseg pbase = ");
697        boot_putw( vseg->pbase ); 
698        boot_puts("\n"); 
699        boot_puts("vseg length = ");
700        boot_putw( vseg->length ); 
701        boot_puts("\n"); 
702        boot_puts("pseg pbase = ");
703        boot_putw( pseg->base ); 
704        boot_puts("\n"); 
705        boot_puts("pseg length = ");
706        boot_putw( pseg->length ); 
707        boot_puts("\n"); 
708        boot_exit();
709    }
710
711    // set the next_base field in vseg
712    if ( vseg->ident == 0 )
713        pseg->next_base = vseg->pbase + vseg->length;
714
715#if BOOT_DEBUG_PT
716boot_puts( vseg->name );
717boot_puts(" : len = ");
718boot_putw( vseg->length );
719boot_puts(" / vbase = ");
720boot_putw( vseg->vbase );
721boot_puts(" / pbase = ");
722boot_putw( vseg->pbase );
723boot_puts("\n");
724#endif 
725
726} // end boot_vseg_map()
727
728/////////////////////////////////////////////////////////////////////
729// This function checks the mapping_info data structure
730/////////////////////////////////////////////////////////////////////
731void boot_check_mapping()
732{
733    mapping_header_t*   header = (mapping_header_t*)&seg_mapping_base; 
734
735    // checking mapping availability
736    if ( header->signature != IN_MAPPING_SIGNATURE )
737    {
738        boot_puts("\n[BOOT ERROR] Illegal mapping signature: ");
739        boot_putw(header->signature);
740        boot_puts("\n");
741        boot_exit();
742    }
743
744#if BOOT_DEBUG_VIEW
745boot_print_mapping_info();
746#endif
747
748    // checking double definition of NB_CLUSTERS
749    if ( header->clusters != NB_CLUSTERS )
750    {
751        boot_puts("\n[BOOT ERROR] Incoherent NB_CLUSTERS");
752        boot_puts("\n             - In giet_config,  value = ");
753        boot_putw ( NB_CLUSTERS );
754        boot_puts("\n             - In mapping_info, value = ");
755        boot_putw ( header->clusters );
756        boot_puts("\n");
757        boot_exit();
758    }
759
760    // checking double definition of NB_TTYS
761    if ( header->ttys != NB_TTYS )
762    {
763        boot_puts("\n[BOOT ERROR] Incoherent NB_TTYS");
764        boot_puts("\n             - In giet_config,  value = ");
765        boot_putw ( NB_TTYS );
766        boot_puts("\n             - In mapping_info, value = ");
767        boot_putw ( header->ttys );
768        boot_puts("\n");
769        boot_exit();
770    }
771
772    // number of virtual spaces no larger than GIET_NB_VSPACE_MAX
773    if ( header->vspaces > GIET_NB_VSPACE_MAX )
774    {
775        boot_puts("\n[BOOT ERROR] : number of vspaces > GIET_NB_VSPACE_MAX\n");
776        boot_puts("\n");
777        boot_exit();
778    }
779} // end boot_check_mapping()
780
781/////////////////////////////////////////////////////////////////////
782// This function builds the page tables for all virtual spaces
783// defined in the mapping_info data structure.
784// For each virtual space, it maps both the global virtual segments
785// (replicated in all vspaces), and the private virtuals segments.
786/////////////////////////////////////////////////////////////////////
787void boot_pt_init()
788{
789    mapping_header_t*   header = (mapping_header_t*)&seg_mapping_base; 
790
791    mapping_vspace_t*   vspace = boot_get_vspace_base( header );     
792    mapping_pseg_t*     pseg   = boot_get_pseg_base( header ); 
793    mapping_vseg_t*     vseg   = boot_get_vseg_base( header );
794
795    unsigned int        vspace_id; 
796    unsigned int        vseg_id;
797    unsigned int        pseg_id;
798
799    // checking mapping_info
800    boot_check_mapping();
801
802    // physical page allocators must be initialised
803    for ( pseg_id = 0 ; pseg_id < header->psegs ; pseg_id++ )
804    {
805        pseg[pseg_id].next_base = pseg[pseg_id].base;
806    }
807
808#if BOOT_DEBUG_PT
809boot_puts("\n******* mapping global vsegs ********\n");
810#endif
811           
812    // step 1 : first loop on virtual spaces to map global vsegs
813    for ( vseg_id = 0 ; vseg_id < header->globals ; vseg_id++ )
814    {
815        boot_vseg_map( &vseg[vseg_id], ((unsigned int)(-1)) );
816    }
817
818    // step 2 : loop on virtual vspaces to map private vsegs
819    for ( vspace_id = 0 ; vspace_id < header->vspaces ; vspace_id++ )
820    {
821
822#if BOOT_DEBUG_PT
823boot_puts("\n******* mapping private vsegs in vspace ");
824boot_puts(vspace[vspace_id].name);
825boot_puts(" ********\n");
826#endif
827           
828        for ( vseg_id = vspace[vspace_id].vseg_offset ; 
829              vseg_id < (vspace[vspace_id].vseg_offset + vspace[vspace_id].vsegs) ; 
830              vseg_id++ )
831        {
832            boot_vseg_map( &vseg[vseg_id], vspace_id ); 
833        }
834    } 
835
836    // step 3 : loop on the vspaces to build the page tables
837    for ( vspace_id = 0 ; vspace_id < header->vspaces ; vspace_id++ )
838    {
839
840#if BOOT_DEBUG_PT
841boot_puts("\n******* building page table for vspace ");
842boot_puts(vspace[vspace_id].name);
843boot_puts(" ********\n");
844#endif
845           
846        boot_vspace_pt_build( vspace_id );
847
848#if BOOT_DEBUG_PT
849boot_puts("\n>>> page table physical address = ");
850boot_putw((unsigned int)_ptabs[vspace_id]);
851boot_puts("\n");
852#endif
853    } 
854
855    boot_puts("\n[BOOT] Page Tables initialisation completed at cycle ");
856    boot_putw( boot_time() );
857    boot_puts("\n");
858
859} // end boot_pt_init()
860
861// Local Variables:
862// tab-width: 4
863// c-basic-offset: 4
864// c-file-offsets:((innamespace . 0)(inline-open . 0))
865// indent-tabs-mode: nil
866// End:
867// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
868
Note: See TracBrowser for help on using the repository browser.