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

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

giet-vm new version

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