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

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

Introducing support for FBDMA (Frame Buffer using DMA)

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 <giet_config.h>
54#include <mapping_info.h>
55#include <mwmr_channel.h>
56
57#include <stdarg.h>
58
59#if !defined(GIET_NB_VSPACE_MAX)
60# error The GIET_NB_VSPACE_MAX value must be defined in the 'giet_config.h' file !
61#endif
62
63#if !defined(GIET_NB_PT2_MAX)
64# error The GIET_NB_PT2_MAX value must be defined in the 'giet_config.h' file !
65#endif
66
67////////////////////////////////////////////////////////////////////////////
68//  Page Tables global variables
69////////////////////////////////////////////////////////////////////////////
70
71// Next free PT2 index array
72unsigned int  _next_free_pt2[GIET_NB_VSPACE_MAX] =
73                         { [0 ... GIET_NB_VSPACE_MAX-1] = 0 };
74
75// Page table pointers array
76page_table_t* _ptabs[GIET_NB_VSPACE_MAX];
77
78//////////////////////////////////////////////////////////////////////////////
79// boot_procid()
80//////////////////////////////////////////////////////////////////////////////
81unsigned int boot_procid()
82{
83    unsigned int ret;
84    asm volatile("mfc0 %0, $15, 1" : "=r"(ret));
85    return (ret & 0x3FF);
86}
87
88//////////////////////////////////////////////////////////////////////////////
89// boot_time()
90//////////////////////////////////////////////////////////////////////////////
91unsigned int boot_time()
92{
93    unsigned int ret;
94    asm volatile("mfc0 %0, $9" : "=r"(ret));
95    return ret;
96}
97
98//////////////////////////////////////////////////////////////////////////////
99// boot_exit()
100//////////////////////////////////////////////////////////////////////////////
101void boot_exit()
102{
103    while(1) asm volatile("nop");
104}
105
106
107////////////////////////////////////////////////////////////////////////////
108// boot_puts()
109// (it uses TTY0)
110////////////////////////////////////////////////////////////////////////////
111void boot_puts(const char *buffer) 
112{
113    unsigned int* tty_address = (unsigned int*)&seg_tty_base;
114    unsigned int n;
115
116    for ( n=0; n<100; n++)
117    {
118        if (buffer[n] == 0) break;
119        tty_address[0] = (unsigned int)buffer[n];
120    }
121   
122} 
123
124////////////////////////////////////////////////////////////////////////////
125// boot_putw()
126// (it uses TTY0)
127////////////////////////////////////////////////////////////////////////////
128void boot_putw(unsigned int val)
129{
130    static const char   HexaTab[] = "0123456789ABCDEF";
131    char                buf[11];
132    unsigned int        c;
133
134    buf[0]  = '0';
135    buf[1]  = 'x';
136    buf[10] = 0;
137
138    for ( c = 0 ; c < 8 ; c++ )
139    { 
140        buf[9-c] = HexaTab[val&0xF];
141        val = val >> 4;
142    }
143    boot_puts(buf);
144}
145
146/////////////////////////////////////////////////////////////////////////////
147// various mapping_info data structure access functions
148/////////////////////////////////////////////////////////////////////////////
149mapping_cluster_t* boot_get_cluster_base( mapping_header_t* header )
150{
151    return   (mapping_cluster_t*) ((char*)header +
152                                  MAPPING_HEADER_SIZE);
153}
154/////////////////////////////////////////////////////////////////////////////
155mapping_pseg_t* boot_get_pseg_base( mapping_header_t* header )
156{
157    return   (mapping_pseg_t*)    ((char*)header +
158                                  MAPPING_HEADER_SIZE +
159                                  MAPPING_CLUSTER_SIZE*header->clusters);
160}
161/////////////////////////////////////////////////////////////////////////////
162mapping_vspace_t* boot_get_vspace_base( mapping_header_t* header )
163{
164    return   (mapping_vspace_t*)  ((char*)header +
165                                  MAPPING_HEADER_SIZE +
166                                  MAPPING_CLUSTER_SIZE*header->clusters +
167                                  MAPPING_PSEG_SIZE*header->psegs);
168}
169/////////////////////////////////////////////////////////////////////////////
170mapping_vseg_t* boot_get_vseg_base( mapping_header_t* header )
171{
172    return   (mapping_vseg_t*)    ((char*)header +
173                                  MAPPING_HEADER_SIZE +
174                                  MAPPING_CLUSTER_SIZE*header->clusters +
175                                  MAPPING_PSEG_SIZE*header->psegs +
176                                  MAPPING_VSPACE_SIZE*header->vspaces);
177}
178/////////////////////////////////////////////////////////////////////////////
179mapping_vobj_t* boot_get_vobj_base( mapping_header_t* header )
180{
181    return   (mapping_vobj_t*)   ((char*)header +
182                                  MAPPING_HEADER_SIZE +
183                                  MAPPING_CLUSTER_SIZE*header->clusters +
184                                  MAPPING_PSEG_SIZE*header->psegs +
185                                  MAPPING_VSPACE_SIZE*header->vspaces +
186                                  MAPPING_VSEG_SIZE*header->vsegs );
187}
188/////////////////////////////////////////////////////////////////////////////
189mapping_task_t* boot_get_task_base( mapping_header_t* header )
190{
191    return   (mapping_task_t*)    ((char*)header +
192                                  MAPPING_HEADER_SIZE +
193                                  MAPPING_CLUSTER_SIZE*header->clusters +
194                                  MAPPING_PSEG_SIZE*header->psegs +
195                                  MAPPING_VSPACE_SIZE*header->vspaces +
196                                  MAPPING_VOBJ_SIZE*header->vobjs +
197                                  MAPPING_VSEG_SIZE*header->vsegs);
198}
199
200/////////////////////////////////////////////////////////////////////////////
201// print the content of the mapping_info data structure
202////////////////////////////////////////////////////////////////////////
203#if BOOT_DEBUG_VIEW
204void boot_print_mapping_info()
205{
206    mapping_header_t*   header = (mapping_header_t*)&seg_mapping_base; 
207   
208    unsigned int                vspace_id;
209    unsigned int                cluster_id;
210    unsigned int                pseg_id;
211    unsigned int                vseg_id;
212    unsigned int                vobj_id;
213    unsigned int                task_id;
214
215    mapping_cluster_t*  cluster = boot_get_cluster_base( header );
216    mapping_pseg_t*         pseg    = boot_get_pseg_base( header );;
217    mapping_vspace_t*   vspace  = boot_get_vspace_base ( header );;
218    mapping_vseg_t*         vseg    = boot_get_vseg_base ( header );
219    mapping_task_t*         task    = boot_get_task_base ( header );;
220    mapping_vobj_t*     vobj    = boot_get_vobj_base( header );
221
222    // header
223    boot_puts("mapping_info");
224
225    boot_puts("\n - signature = ");
226    boot_putw(header->signature);
227    boot_puts("\n - name      = ");
228    boot_puts(header->name);
229    boot_puts("\n - clusters  = ");
230    boot_putw(header->clusters);
231    boot_puts("\n - psegs     = ");
232    boot_putw(header->psegs);
233    boot_puts("\n - ttys      = ");
234    boot_putw(header->ttys);
235    boot_puts("\n - fbs       = ");
236    boot_putw(header->fbs);
237    boot_puts("\n - vspaces   = ");
238    boot_putw(header->vspaces);
239    boot_puts("\n - globals   = ");
240    boot_putw(header->globals);
241    boot_puts("\n - vsegs     = ");
242    boot_putw(header->vsegs);
243    boot_puts("\n - vobjs     = ");
244    boot_putw(header->vobjs);
245    boot_puts("\n - tasks     = ");
246    boot_putw(header->tasks);
247    boot_puts("\n\n");
248
249    // clusters
250    for ( cluster_id = 0 ; cluster_id < header->clusters ; cluster_id++ )
251    {
252        boot_puts("cluster ");
253        boot_putw(cluster_id);
254
255        boot_puts("\n - procs  = ");
256        boot_putw(cluster[cluster_id].procs);
257        boot_puts("\n\n");
258    }
259
260    // psegs
261    for ( pseg_id = 0 ; pseg_id < header->psegs ; pseg_id++ )
262    {
263        boot_puts("pseg ");
264        boot_putw(pseg_id);
265
266        boot_puts("\n - name   = ");
267        boot_puts( pseg[pseg_id].name );
268        boot_puts("\n - base   = ");
269        boot_putw( pseg[pseg_id].base );
270        boot_puts("\n - length = ");
271        boot_putw( pseg[pseg_id].length );
272        boot_puts("\n\n");
273    }
274
275    // globals
276    for ( vseg_id = 0 ; vseg_id < header->globals ; vseg_id++ )
277    {
278        boot_puts("global vseg ");
279        boot_putw(vseg_id);
280
281        boot_puts("\n - name        = ");
282        boot_puts( vseg[vseg_id].name );
283        boot_puts("\n - vbase       = ");
284        boot_putw( vseg[vseg_id].vbase );
285        boot_puts("\n - length      = ");
286        boot_putw( vseg[vseg_id].length );
287        boot_puts("\n - mode        = ");
288        boot_putw( vseg[vseg_id].mode );
289        boot_puts("\n - ident       = ");
290        boot_putw( vseg[vseg_id].ident );
291        boot_puts("\n - psegname    = ");
292        boot_puts( pseg[vseg[vseg_id].psegid].name );
293        boot_puts("\n - vobjs       = ");
294        boot_putw( vseg[vseg_id].vobjs );
295        boot_puts("\n - vobj_offset = ");
296        boot_putw( vseg[vseg_id].vobj_offset );
297        boot_puts("\n");
298        for ( vobj_id = vseg[vseg_id].vobj_offset ; 
299              vobj_id < vseg[vseg_id].vobj_offset + vseg[vseg_id].vobjs ; 
300              vobj_id++ )
301        {
302                        boot_puts("\n\t vobj ");
303            boot_puts( vobj[vobj_id].name);
304            boot_puts("\n\t type     = ");
305                        boot_putw( vobj[vobj_id].type);
306            boot_puts("\n\t length   = ");
307                        boot_putw(   vobj[vobj_id].length);
308            boot_puts("\n\t align    = ");
309                        boot_putw(   vobj[vobj_id].align);
310            boot_puts("\n\t binpath  = ");
311                        boot_puts(   vobj[vobj_id].binpath);
312                        boot_puts("\n\n");
313        }
314    }
315
316    // vspaces
317    for ( vspace_id = 0 ; vspace_id < header->vspaces ; vspace_id++ )
318    {
319        unsigned int start_id = vspace[vspace_id].vobj_offset + 
320                                vspace[vspace_id].start_offset; 
321
322        boot_puts("vspace ");
323        boot_putw(vspace_id);
324
325        boot_puts("\n - name        = ");
326        boot_puts( vspace[vspace_id].name ); 
327        boot_puts("\n - start_vobj  = ");
328        boot_puts( vobj[start_id].name ); 
329        boot_puts("\n - vsegs       = ");
330        boot_putw( vspace[vspace_id].vsegs ); 
331        boot_puts("\n - vobjs       = ");
332        boot_putw( vspace[vspace_id].vobjs ); 
333        boot_puts("\n - tasks       = ");
334        boot_putw( vspace[vspace_id].tasks ); 
335        boot_puts("\n - vseg_offset = ");
336        boot_putw( vspace[vspace_id].vseg_offset ); 
337        boot_puts("\n - vobj_offset = ");
338        boot_putw( vspace[vspace_id].vobj_offset ); 
339        boot_puts("\n - task_offset = ");
340        boot_putw( vspace[vspace_id].task_offset ); 
341        boot_puts("\n\n");
342
343        for ( vseg_id = vspace[vspace_id].vseg_offset ; 
344              vseg_id < (vspace[vspace_id].vseg_offset + vspace[vspace_id].vsegs) ; 
345              vseg_id++ )
346        {
347            boot_puts("    private vseg ");
348            boot_putw( vseg_id );
349
350            boot_puts("\n    - name        = ");
351            boot_puts( vseg[vseg_id].name );
352            boot_puts("\n    - vbase       = ");
353            boot_putw( vseg[vseg_id].vbase );
354            boot_puts("\n    - length      = ");
355            boot_putw( vseg[vseg_id].length );
356            boot_puts("\n    - mode        = ");
357            boot_putw( vseg[vseg_id].mode );
358            boot_puts("\n    - ident       = ");
359            boot_putw( vseg[vseg_id].ident );
360            boot_puts("\n    - psegname    = ");
361            boot_puts( pseg[vseg[vseg_id].psegid].name );
362            boot_puts("\n    - vobjs       = ");
363            boot_putw( vseg[vseg_id].vobjs );
364            boot_puts("\n    - vobj_offset = ");
365            boot_putw( vseg[vseg_id].vobj_offset );
366            boot_puts("\n");
367
368            for ( vobj_id = vseg[vseg_id].vobj_offset ; 
369                  vobj_id < vseg[vseg_id].vobj_offset + vseg[vseg_id].vobjs ; 
370                  vobj_id++ )
371            {
372                boot_puts("\n\t\t vobj ");
373                boot_puts( vobj[vobj_id].name);
374                boot_puts("\n\t\t type     = ");
375                boot_putw( vobj[vobj_id].type);
376                boot_puts("\n\t\t length   = ");
377                            boot_putw(   vobj[vobj_id].length);
378                boot_puts("\n\t\t align    = ");
379                            boot_putw(   vobj[vobj_id].align);
380                boot_puts("\n\t\t binpath  = ");
381                        boot_puts(   vobj[vobj_id].binpath);
382                        boot_puts("\n\n");
383            }
384        }
385
386        for ( task_id = vspace[vspace_id].vseg_offset ; 
387              task_id < (vspace[vspace_id].task_offset + vspace[vspace_id].tasks) ; 
388              task_id++ )
389        {
390            boot_puts("     task");
391            boot_putw( task_id );
392
393            boot_puts("\n     - name = ");
394            boot_puts( task[task_id].name );
395            boot_puts("\n     - clusterid = ");
396            boot_putw( task[task_id].clusterid );
397            boot_puts("\n     - proclocid = ");
398            boot_putw( task[task_id].proclocid );
399            boot_puts("\n     - vobjlocid = ");
400            boot_putw( task[task_id].vobjlocid );
401            boot_puts("\n     - startid   = ");
402            boot_putw( task[task_id].startid );
403            boot_puts("\n     - use_tty   = ");
404            boot_putw( task[task_id].use_tty );
405            boot_puts("\n     - use_fb   = ");
406            boot_putw( task[task_id].use_fb );
407            boot_puts("\n\n");
408        }
409    }
410} // end boot_print_mapping_info()
411#endif
412
413//////////////////////////////////////////////////////////////////////////////
414// boot_pseg_get()
415// This function returns the pointer on a physical segment
416// identified  by the pseg index.
417//////////////////////////////////////////////////////////////////////////////
418mapping_pseg_t* boot_pseg_get( unsigned int seg_id)
419{
420    mapping_header_t* header = (mapping_header_t*)&seg_mapping_base;
421    mapping_pseg_t*   pseg   = boot_get_pseg_base( header );
422
423    // checking argument
424    if ( seg_id >= header->psegs )
425    {
426        boot_puts("\n[BOOT ERROR] : seg_id argument too large\n");
427        boot_puts("               in function boot_pseg_get()\n");
428        boot_exit();
429    }
430
431    return &pseg[seg_id];                                   
432} // end boot_pseg_get()
433
434//////////////////////////////////////////////////////////////////////////////
435// boot_add_pte()
436// This function registers a new PTE in the page table pointed
437// by the vspace_id argument, and updates both PT1 and PT2.
438// A new PT2 is used when required.
439// As the set of PT2s is implemented as a fixed size array (no dynamic
440// allocation), this function checks a possible overflow of the PT2 array.
441//
442// The global parameter is a boolean indicating wether a global vseg is
443// being mapped.
444//////////////////////////////////////////////////////////////////////////////
445void boot_add_pte( unsigned int    vspace_id,   
446                   unsigned int    vpn,           
447                   unsigned int    flags,
448                   unsigned int    ppn )
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    page_table_t* pt = (page_table_t *)_ptabs[vspace_id];
461    if ( (pt->pt1[ix1] & PTE_V) == 0 )   // set a new PTD in PT1
462    {
463        pt2_id = _next_free_pt2[vspace_id];
464        if ( pt2_id == GIET_NB_PT2_MAX )
465        {
466            boot_puts("\n[BOOT ERROR] in boot_add_pte() function\n");
467            boot_puts("the length of the ptab vobj is too small\n"); 
468            boot_exit();
469        }
470        else
471        {
472            ptba = (unsigned int)pt + PT1_SIZE + PT2_SIZE*pt2_id;
473            pt->pt1[ix1] = PTE_V | PTE_T | (ptba >> 12);   
474            _next_free_pt2[vspace_id] = pt2_id + 1;
475        }
476    }
477    else
478    {
479        ptba = pt->pt1[ix1] << 12;
480    }
481
482    // set PTE2 after checking double mapping error
483    pt_flags = (unsigned int*)(ptba + 8*ix2);
484    pt_ppn   = (unsigned int*)(ptba + 8*ix2 + 4);
485
486    if ( ( *pt_flags & PTE_V) != 0 )    // page already mapped
487    {
488        boot_puts("\n[BOOT ERROR] in boot_add_pte() function\n");
489        boot_puts("page already mapped\n");
490        boot_exit();
491    }
492
493    // set PTE2
494    *pt_flags = flags;
495    *pt_ppn   = ppn;
496
497} // end boot_add_pte()
498               
499/////////////////////////////////////////////////////////////////////
500// This function build the page table for a given vspace.
501// The physical base addresses for all vsegs (global and private)
502// must have been previously computed.
503// It initializes the MWMR channels.
504/////////////////////////////////////////////////////////////////////
505void boot_vspace_pt_build( unsigned int vspace_id )
506{
507    unsigned int    vseg_id;
508    unsigned int    npages;
509    unsigned int    ppn;
510    unsigned int    vpn;
511    unsigned int    flags;
512    unsigned int    page_id;
513
514    mapping_header_t*  header = (mapping_header_t*)&seg_mapping_base; 
515    mapping_vspace_t*  vspace = boot_get_vspace_base( header );
516    mapping_vseg_t*    vseg   = boot_get_vseg_base( header );
517   
518    // private segments
519    for ( vseg_id = vspace[vspace_id].vseg_offset ; 
520          vseg_id < (vspace[vspace_id].vseg_offset + vspace[vspace_id].vsegs) ; 
521          vseg_id++ )
522    {
523        vpn       = vseg[vseg_id].vbase >> 12;
524        ppn       = vseg[vseg_id].pbase >> 12;
525        npages    = vseg[vseg_id].length >> 12;
526        if ( (vseg[vseg_id].length & 0xFFF) != 0 ) npages++;
527
528        flags = PTE_V;
529        if ( vseg[vseg_id].mode & C_MODE_MASK )  flags = flags | PTE_C;
530        if ( vseg[vseg_id].mode & X_MODE_MASK )  flags = flags | PTE_X;
531        if ( vseg[vseg_id].mode & W_MODE_MASK )  flags = flags | PTE_W;
532        if ( vseg[vseg_id].mode & U_MODE_MASK )  flags = flags | PTE_U;
533
534#if BOOT_DEBUG_PT
535boot_puts("- vseg ");
536boot_puts( vseg[vseg_id].name );
537boot_puts(" / flags = ");
538boot_putw( flags );
539boot_puts(" / npages = ");
540boot_putw( npages );
541boot_puts("\n");
542#endif       
543        // loop on 4K pages
544        for ( page_id = 0 ; page_id < npages ; page_id++ )
545        {
546            boot_add_pte( vspace_id,
547                          vpn,
548                          flags,
549                          ppn );
550            vpn++;
551            ppn++;
552        }
553    }
554
555    // global segments
556    for ( vseg_id = 0 ; vseg_id < header->globals ; vseg_id++ )
557    {
558        vpn       = vseg[vseg_id].vbase >> 12;
559        ppn       = vseg[vseg_id].pbase >> 12;
560        npages    = vseg[vseg_id].length >> 12;
561        if ( (vseg[vseg_id].length & 0xFFF) != 0 ) npages++;
562
563        flags = PTE_V;
564        if ( vseg[vseg_id].mode & C_MODE_MASK )  flags = flags | PTE_C;
565        if ( vseg[vseg_id].mode & X_MODE_MASK )  flags = flags | PTE_X;
566        if ( vseg[vseg_id].mode & W_MODE_MASK )  flags = flags | PTE_W;
567        if ( vseg[vseg_id].mode & U_MODE_MASK )  flags = flags | PTE_U;
568
569#if BOOT_DEBUG_PT
570boot_puts("- vseg ");
571boot_puts( vseg[vseg_id].name );
572boot_puts(" / flags = ");
573boot_putw( flags );
574boot_puts(" / npages = ");
575boot_putw( npages );
576boot_puts("\n");
577#endif       
578        // loop on 4K pages
579        for ( page_id = 0 ; page_id < npages ; page_id++ )
580        {
581            boot_add_pte( vspace_id,
582                          vpn,
583                          flags,
584                          ppn );
585            vpn++;
586            ppn++;
587        }
588    }
589
590} // end boot_vspace_pt_build()
591
592///////////////////////////////////////////////////////////////////////////
593// Align the value "toAlign" to the required alignement indicated by
594// alignPow2 ( the logarithme of 2 the alignement).
595///////////////////////////////////////////////////////////////////////////
596unsigned int align_to( unsigned int toAlign, 
597                       unsigned int alignPow2)
598{
599    unsigned int    mask = (1 << alignPow2) - 1;
600    return ((toAlign + mask ) & ~mask ); 
601}
602
603///////////////////////////////////////////////////////////////////////////
604// This function compute the physical base address for a vseg
605// as specified in the mapping info data structure.
606// It updates the pbase and the length fields of the vseg.
607// It updates the pbase and vbase fields of all vobjs in the vseg.
608// It updates the next_base field of the pseg.
609// It checks a possible pseg overflow.
610// It is a global vseg if vspace_id = (-1)
611///////////////////////////////////////////////////////////////////////////
612void boot_vseg_map( mapping_vseg_t*     vseg, 
613                    unsigned int        vspace_id ) 
614{
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.