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

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

Introducing support for FBDMA (Frame Buffer using DMA)

File size: 30.6 KB
RevLine 
[160]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.
[165]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.
[160]10//
[165]11// The SoCLib generic MMU (paged virtual memory) provides two services:
[160]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//
[165]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).
[160]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
[167]33// defined by the (GIET_NB_PT2_MAX) configuration parameter.
[160]34// The max number of virtual spaces (GIET_NB_VSPACE_MAX) is a configuration parameter.
35//
[167]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.
[160]43//   The PT1 contains 2048 PTD of 4 bytes => 8K bytes.
[167]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.
[160]49////////////////////////////////////////////////////////////////////////////////////
50
[165]51#include "../sys/mips32_registers.h"
[160]52#include <boot_handler.h>
[169]53#include <giet_config.h>
[160]54#include <mapping_info.h>
[165]55#include <mwmr_channel.h>
[160]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
[167]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
[160]67////////////////////////////////////////////////////////////////////////////
[165]68//  Page Tables global variables
[160]69////////////////////////////////////////////////////////////////////////////
70
[165]71// Next free PT2 index array
[160]72unsigned int  _next_free_pt2[GIET_NB_VSPACE_MAX] =
73                         { [0 ... GIET_NB_VSPACE_MAX-1] = 0 };
74
[165]75// Page table pointers array
[160]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////////////////////////////////////////////////////////////////////////////
[165]108// boot_puts()
[160]109// (it uses TTY0)
110////////////////////////////////////////////////////////////////////////////
[165]111void boot_puts(const char *buffer) 
[160]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////////////////////////////////////////////////////////////////////////////
[165]125// boot_putw()
[160]126// (it uses TTY0)
127////////////////////////////////////////////////////////////////////////////
[165]128void boot_putw(unsigned int val)
[160]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    }
[165]143    boot_puts(buf);
[160]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 );;
[165]220    mapping_vobj_t*     vobj    = boot_get_vobj_base( header );
[160]221
222    // header
[165]223    boot_puts("mapping_info");
[160]224
[165]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");
[160]248
249    // clusters
250    for ( cluster_id = 0 ; cluster_id < header->clusters ; cluster_id++ )
251    {
[165]252        boot_puts("cluster ");
253        boot_putw(cluster_id);
[160]254
[165]255        boot_puts("\n - procs  = ");
256        boot_putw(cluster[cluster_id].procs);
257        boot_puts("\n\n");
[160]258    }
259
260    // psegs
261    for ( pseg_id = 0 ; pseg_id < header->psegs ; pseg_id++ )
262    {
[165]263        boot_puts("pseg ");
264        boot_putw(pseg_id);
[160]265
[165]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");
[160]273    }
274
275    // globals
276    for ( vseg_id = 0 ; vseg_id < header->globals ; vseg_id++ )
277    {
[165]278        boot_puts("global vseg ");
279        boot_putw(vseg_id);
[160]280
[165]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++ )
[160]301        {
[165]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");
[160]313        }
314    }
315
316    // vspaces
317    for ( vspace_id = 0 ; vspace_id < header->vspaces ; vspace_id++ )
318    {
[165]319        unsigned int start_id = vspace[vspace_id].vobj_offset + 
320                                vspace[vspace_id].start_offset; 
[160]321
[165]322        boot_puts("vspace ");
323        boot_putw(vspace_id);
[160]324
[165]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
[160]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        {
[165]347            boot_puts("    private vseg ");
348            boot_putw( vseg_id );
[160]349
[165]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++ )
[160]371            {
[165]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");
[160]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        {
[165]390            boot_puts("     task");
391            boot_putw( task_id );
[160]392
[165]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");
[160]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
[165]416// identified  by the pseg index.
[160]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    {
[165]426        boot_puts("\n[BOOT ERROR] : seg_id argument too large\n");
427        boot_puts("               in function boot_pseg_get()\n");
[160]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.
[163]441//
[167]442// The global parameter is a boolean indicating wether a global vseg is
[163]443// being mapped.
[160]444//////////////////////////////////////////////////////////////////////////////
445void boot_add_pte( unsigned int    vspace_id,   
[163]446                   unsigned int    vpn,           
447                   unsigned int    flags,
[167]448                   unsigned int    ppn )
[160]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
[167]460    page_table_t* pt = (page_table_t *)_ptabs[vspace_id];
[160]461    if ( (pt->pt1[ix1] & PTE_V) == 0 )   // set a new PTD in PT1
462    {
463        pt2_id = _next_free_pt2[vspace_id];
[167]464        if ( pt2_id == GIET_NB_PT2_MAX )
[160]465        {
[165]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"); 
[160]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    {
[165]488        boot_puts("\n[BOOT ERROR] in boot_add_pte() function\n");
489        boot_puts("page already mapped\n");
490        boot_exit();
[160]491    }
[163]492
493    // set PTE2
494    *pt_flags = flags;
495    *pt_ppn   = ppn;
496
[160]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 );
[163]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++ )
[160]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
[165]535boot_puts("- vseg ");
536boot_puts( vseg[vseg_id].name );
537boot_puts(" / flags = ");
538boot_putw( flags );
539boot_puts(" / npages = ");
540boot_putw( npages );
541boot_puts("\n");
[160]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,
[167]549                          ppn );
[160]550            vpn++;
551            ppn++;
552        }
553    }
[163]554
555    // global segments
556    for ( vseg_id = 0 ; vseg_id < header->globals ; vseg_id++ )
[160]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
[165]570boot_puts("- vseg ");
571boot_puts( vseg[vseg_id].name );
572boot_puts(" / flags = ");
573boot_putw( flags );
574boot_puts(" / npages = ");
575boot_putw( npages );
576boot_puts("\n");
[160]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,
[167]584                          ppn );
[160]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///////////////////////////////////////////////////////////////////////////
[165]596unsigned int align_to( unsigned int toAlign, 
597                       unsigned int alignPow2)
[160]598{
[165]599    unsigned int    mask = (1 << alignPow2) - 1;
600    return ((toAlign + mask ) & ~mask ); 
[160]601}
602
603///////////////////////////////////////////////////////////////////////////
604// This function compute the physical base address for a vseg
605// as specified in the mapping info data structure.
[167]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.
[165]610// It is a global vseg if vspace_id = (-1)
[160]611///////////////////////////////////////////////////////////////////////////
[165]612void boot_vseg_map( mapping_vseg_t*     vseg, 
613                    unsigned int        vspace_id ) 
[160]614{
[165]615    unsigned int        vobj_id;
616    unsigned int        cur_vaddr;
617    unsigned int        cur_paddr;
[160]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    {
[165]627         vseg->pbase = vseg->vbase;
[160]628    }
629    else                                // unconstrained mapping
630    {
[167]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        }
[160]638    }
639   
[167]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
[160]644    cur_vaddr = vseg->vbase;
645    cur_paddr = vseg->pbase;
[165]646
647    for( vobj_id = vseg->vobj_offset; 
648         vobj_id < (vseg->vobj_offset + vseg->vobjs); 
649         vobj_id++)
[160]650    {
[165]651        if ( vobj[vobj_id].align )
[160]652        {
653            cur_paddr = align_to(cur_paddr, vobj[vobj_id].align);
654        }
655
[167]656        // set vaddr/paddr for current vobj
[160]657        vobj[vobj_id].vaddr = cur_vaddr;       
658        vobj[vobj_id].paddr = cur_paddr; 
659     
[165]660        // set next vaddr/paddr
[160]661        cur_vaddr += vobj[vobj_id].length;
662        cur_paddr += vobj[vobj_id].length; 
[165]663
[167]664        // initialise _ptabs[] if current vobj is a PTAB
[165]665        if ( vobj[vobj_id].type == VOBJ_TYPE_PTAB )
666        {
[167]667            if(vobj[vobj_id].length < (PT1_SIZE + PT2_SIZE*GIET_NB_PT2_MAX) ) 
[165]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            }
[167]681            _ptabs[vspace_id] = (page_table_t*)vobj[vobj_id].paddr;
[165]682        }
[167]683    } // end for vobjs
[160]684   
[165]685    //set the vseg length
[167]686    vseg->length = align_to( (cur_paddr - vseg->pbase), 12);
[160]687
[165]688    // checking pseg overflow
689    if ( (vseg->pbase < pseg->base) || 
[167]690         ((vseg->pbase + vseg->length) > (pseg->base + pseg->length)) )
[165]691    {
692        boot_puts("\n[BOOT ERROR] in boot_vseg_map() function\n");
[167]693        boot_puts("impossible mapping for virtual segment: ");
[165]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
[167]711    // set the next_base field in vseg
712    if ( vseg->ident == 0 )
713        pseg->next_base = vseg->pbase + vseg->length;
[160]714
715#if BOOT_DEBUG_PT
[165]716boot_puts( vseg->name );
[167]717boot_puts(" : len = ");
718boot_putw( vseg->length );
719boot_puts(" / vbase = ");
[165]720boot_putw( vseg->vbase );
721boot_puts(" / pbase = ");
722boot_putw( vseg->pbase );
723boot_puts("\n");
[160]724#endif 
725
726} // end boot_vseg_map()
727
728/////////////////////////////////////////////////////////////////////
[165]729// This function checks the mapping_info data structure
[160]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    {
[165]738        boot_puts("\n[BOOT ERROR] Illegal mapping signature: ");
739        boot_putw(header->signature);
740        boot_puts("\n");
[160]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    {
[165]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");
[160]757        boot_exit();
758    }
759
760    // checking double definition of NB_TTYS
761    if ( header->ttys != NB_TTYS )
762    {
[165]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");
[160]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    {
[165]775        boot_puts("\n[BOOT ERROR] : number of vspaces > GIET_NB_VSPACE_MAX\n");
776        boot_puts("\n");
[160]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
[165]799    // checking mapping_info
800    boot_check_mapping();
[160]801
[165]802    // physical page allocators must be initialised
[160]803    for ( pseg_id = 0 ; pseg_id < header->psegs ; pseg_id++ )
804    {
[167]805        pseg[pseg_id].next_base = pseg[pseg_id].base;
[160]806    }
807
[165]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
[160]813    for ( vseg_id = 0 ; vseg_id < header->globals ; vseg_id++ )
814    {
815        boot_vseg_map( &vseg[vseg_id], ((unsigned int)(-1)) );
816    }
817
[165]818    // step 2 : loop on virtual vspaces to map private vsegs
[160]819    for ( vspace_id = 0 ; vspace_id < header->vspaces ; vspace_id++ )
820    {
821
822#if BOOT_DEBUG_PT
[165]823boot_puts("\n******* mapping private vsegs in vspace ");
824boot_puts(vspace[vspace_id].name);
825boot_puts(" ********\n");
[160]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
[165]836    // step 3 : loop on the vspaces to build the page tables
[160]837    for ( vspace_id = 0 ; vspace_id < header->vspaces ; vspace_id++ )
838    {
839
840#if BOOT_DEBUG_PT
[165]841boot_puts("\n******* building page table for vspace ");
842boot_puts(vspace[vspace_id].name);
843boot_puts(" ********\n");
[160]844#endif
845           
846        boot_vspace_pt_build( vspace_id );
[165]847
848#if BOOT_DEBUG_PT
[167]849boot_puts("\n>>> page table physical address = ");
850boot_putw((unsigned int)_ptabs[vspace_id]);
[165]851boot_puts("\n");
852#endif
[160]853    } 
854
[165]855    boot_puts("\n[BOOT] Page Tables initialisation completed at cycle ");
856    boot_putw( boot_time() );
857    boot_puts("\n");
[160]858
[165]859} // end boot_pt_init()
[160]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.