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

Last change on this file since 182 was 180, checked in by karaoui, 14 years ago

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

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