- Timestamp:
- Feb 8, 2015, 12:30:47 PM (10 years ago)
- Location:
- soft/giet_vm/giet_boot
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
soft/giet_vm/giet_boot/boot.c
r490 r493 1 /////////////////////////////////////////////////////////////////////////////////////// //1 /////////////////////////////////////////////////////////////////////////////////////// 2 2 // File : boot.c 3 3 // Date : 01/11/2013 4 4 // Author : alain greiner 5 5 // Copyright (c) UPMC-LIP6 6 /////////////////////////////////////////////////////////////////////////////////////// ///7 // The boot.c file is part of the GIET-VM nano-kernel.6 /////////////////////////////////////////////////////////////////////////////////////// 7 // The boot.c file contains the bootloader for the GIET-VM static OS. 8 8 // 9 // This nano-kernelhas been written for the MIPS32 processor.9 // This code has been written for the MIPS32 processor. 10 10 // The virtual adresses are on 32 bits and use the (unsigned int) type. The 11 11 // physicals addresses can have up to 40 bits, and use the (unsigned long long) type. 12 12 // It natively supports clusterised shared memory multi-processors architectures, 13 // where each processor is identified by a composite index (cluster_xy, local_id),13 // where each processor is identified by a composite index [x,y,p], 14 14 // and where there is one physical memory bank per cluster. 15 15 // 16 // This code, executed in the boot phase by proc[0,0,0], performs the following tasks: 17 // - load into memory various binary files, from a FAT32 file system, 18 // - build the various page tables (one page table per vspace) 19 // - initialize the shedulers (one scheduler per processor) 16 // The boot.elf file is stored on disk and is loaded into memory by proc[0,0,0], 17 // executing the generic preloader (stored in ROM). The boot-loader code itself 18 // is executed in parallel by all proc[x,y,0], and performs the following tasks: 19 // - load into memory various binary files, from a FAT32 file system. 20 // - build the various page tables (one page table per vspace). 21 // - initialize the shedulers (one scheduler per processor). 22 // - initialize the external peripherals. 20 23 // 21 24 // 1) The binary files to be loaded are: … … 23 26 // mapping directives. It must be stored in the the seg_boot_mapping segment 24 27 // (at address SEG_BOOT_MAPPING_BASE defined in hard_config.h file). 25 // - the " sys.elf" file contains the kernel binary code and data.28 // - the "kernel.elf" file contains the kernel binary code and data. 26 29 // - the various "application.elf" files. 27 30 // 28 // 2) The map.bin file contains the binary representation of the map.xml file defining:31 // 2) The "map.bin" file contains the C binary structure defining: 29 32 // - the hardware architecture: number of clusters, number or processors, 30 33 // size of the memory segments, and peripherals in each cluster. … … 41 44 // of the software objects (vsegs) on the physical memory banks (psegs). 42 45 // 43 // The max number of vspaces (GIET_NB_VSPACE_MAX) is a configuration parameter. 46 // The max number of vspaces (GIET_NB_VSPACE_MAX) is a configuration parameter, 47 // and - for each application - the tasks are statically allocateded on procesors. 44 48 // The page table are statically build in the boot phase, and they do not 45 49 // change during execution. … … 52 56 // A PT2 is indexed the ix2 field (9 bits) of the VPN. Each entry is a double word. 53 57 // The first word contains the flags, the second word contains the PPN. 54 // 55 // When this is required in the mapping, the page tables can be replicated 56 // in all clusters. 58 // The page tables are distributed/replicated in all clusters. 57 59 /////////////////////////////////////////////////////////////////////////////////////// 58 60 // Implementation Notes: 59 61 // 60 62 // 1) The cluster_id variable is a linear index in the mapping_info array of clusters. 61 // We use the cluster_xy variable forthe tological index = x << Y_WIDTH + y63 // The cluster_xy variable is the tological index = x << Y_WIDTH + y 62 64 // 65 // 2) We set the _tty0_boot_mode variable to force the _printf() function to use 66 // the tty0_spin_lock for exclusive access to TTY0. 63 67 /////////////////////////////////////////////////////////////////////////////////////// 64 68 … … 67 71 #include <mapping_info.h> 68 72 #include <kernel_malloc.h> 69 #include <barrier.h>70 73 #include <memspace.h> 71 74 #include <tty_driver.h> … … 86 89 #include <utils.h> 87 90 #include <tty0.h> 88 #include <locks.h> 91 #include <kernel_locks.h> 92 #include <kernel_barriers.h> 89 93 #include <elf-types.h> 90 94 #include <fat32.h> … … 131 135 132 136 // FAT internal representation for boot code 133 __attribute__((section (".bootdata")))134 fat32_fs_t 137 __attribute__((section(".kdata"))) 138 fat32_fs_t fat __attribute__((aligned(512))); 135 139 136 140 // Temporaty buffer used to load one complete .elf file 137 __attribute__((section (".bootdata")))138 char 141 __attribute__((section(".kdata"))) 142 char boot_elf_buffer[GIET_ELF_BUFFER_SIZE] __attribute__((aligned(512))); 139 143 140 144 // Physical memory allocators array (one per cluster) 141 __attribute__((section (".bootdata")))142 pmem_alloc_t 145 __attribute__((section(".kdata"))) 146 pmem_alloc_t boot_pmem_alloc[X_SIZE][Y_SIZE]; 143 147 144 148 // Distributed kernel heap (one per cluster) 145 __attribute__((section (".bootdata"))) 146 kernel_heap_tkernel_heap[X_SIZE][Y_SIZE];149 // __attribute__((section(".kdata"))) 150 // kernel_heap_t kernel_heap[X_SIZE][Y_SIZE]; 147 151 148 152 // Schedulers virtual base addresses array (one per processor) 149 __attribute__((section (".bootdata")))150 static_scheduler_t* 153 __attribute__((section(".kdata"))) 154 static_scheduler_t* _schedulers[X_SIZE][Y_SIZE][NB_PROCS_MAX]; 151 155 152 156 // Page tables virtual base addresses array (one per vspace) 153 __attribute__((section (".bootdata")))154 unsigned int 157 __attribute__((section(".kdata"))) 158 unsigned int _ptabs_vaddr[GIET_NB_VSPACE_MAX][X_SIZE][Y_SIZE]; 155 159 156 160 // Page tables physical base addresses (one per vspace and per cluster) 157 __attribute__((section (".bootdata")))158 paddr_t 161 __attribute__((section(".kdata"))) 162 paddr_t _ptabs_paddr[GIET_NB_VSPACE_MAX][X_SIZE][Y_SIZE]; 159 163 160 164 // Page tables pt2 allocators (one per vspace and per cluster) 161 __attribute__((section (".bootdata")))162 unsigned int 165 __attribute__((section(".kdata"))) 166 unsigned int _ptabs_next_pt2[GIET_NB_VSPACE_MAX][X_SIZE][Y_SIZE]; 163 167 164 168 // Page tables max_pt2 (same value for all page tables) 165 __attribute__((section (".bootdata"))) 166 unsigned int _ptabs_max_pt2; 167 168 __attribute__((section (".bootdata"))) 169 //volatile struct _boot_init_ok { 170 // unsigned int value; 171 //}__attribute__((aligned(64))); 172 //struct _boot_init_ok boot_init_ok = {0}; 173 volatile unsigned int boot_init_ok = 0; 174 175 __attribute__((section (".bootdata"))) 176 volatile _giet_lock_t lock_tty; 177 178 __attribute__((section (".bootdata"))) 179 volatile _giet_barrier_t barrier_boot; 180 181 __attribute__((section (".bootdata"))) 182 volatile _giet_lock_t lock_next_pt2[GIET_NB_VSPACE_MAX][X_SIZE][Y_SIZE]; 183 184 // Global variables for TTY 185 __attribute__((section (".bootdata"))) 186 sbt_lock_t _tty_tx_lock[NB_TTY_CHANNELS] __attribute__((aligned(64))); 187 188 __attribute__((section (".bootdata"))) 189 unsigned int _tty_rx_full[NB_TTY_CHANNELS]; 190 #if BOOT_DEBUG_MAPPING 191 unsigned int word; 192 unsigned int line; 193 unsigned int* pointer = (unsigned int*)SEG_BOOT_MAPPING_BASE; 194 _puts("\n[BOOT] First block of mapping"); 195 for ( line = 0 ; line < 8 ; line++ ) 196 { 197 for ( word = 0 ; word < 8 ; word++ ) 198 { 199 _puts(" | "); 200 _putx( *(pointer + word) ); 201 } 202 _puts(" |\n"); 203 pointer = pointer + 8; 204 } 205 #endif 206 207 __attribute__((section (".bootdata"))) 208 unsigned int _tty_rx_buf[NB_TTY_CHANNELS]; 169 __attribute__((section(".kdata"))) 170 unsigned int _ptabs_max_pt2; 171 172 // WTI channel allocator (one per cluster) 173 __attribute__((section(".kdata"))) 174 unsigned int _wti_channel_alloc[X_SIZE][Y_SIZE]; 175 176 // boot code uses a spin lock to protect TTY0 177 __attribute__((section(".kdata"))) 178 unsigned int _tty0_boot_mode = 1; 179 180 __attribute__((section(".kdata"))) 181 spin_lock_t _ptabs_spin_lock[GIET_NB_VSPACE_MAX][X_SIZE][Y_SIZE]; 182 183 // barrier used by boot code for parallel execution 184 __attribute__((section(".kdata"))) 185 simple_barrier_t _barrier_all_clusters; 186 187 // this variable is defined in the tty0.c file 188 extern spin_lock_t _tty0_spin_lock; 209 189 210 190 ////////////////////////////////////////////////////////////////////////////// … … 212 192 // by the vspace_id argument, and the (x,y) coordinates. 213 193 // It updates only the first level PT1. 194 // As each vseg is mapped by a different processor, the PT1 entry cannot 195 // be concurrently accessed, and we don't need to take any lock. 214 196 ////////////////////////////////////////////////////////////////////////////// 215 197 void boot_add_pte1( unsigned int vspace_id, … … 220 202 unsigned int ppn ) // 28 bits right-justified 221 203 { 222 223 #if (BOOT_DEBUG_PT > 1)224 _get_lock(&lock_tty);225 _puts(" - PTE1 in PTAB[");226 _putd( vspace_id );227 _puts(",");228 _putd( x );229 _puts(",");230 _putd( y );231 _puts("] : vpn = ");232 _putx( vpn );233 _puts(" / ppn = ");234 _putx( ppn );235 _puts(" / flags = ");236 _putx( flags );237 _puts("\n");238 _release_lock(&lock_tty);239 #endif240 241 unsigned int procid = _get_procid();242 unsigned int x_cluster = (procid >> (Y_WIDTH + P_WIDTH)) & ((1<<X_WIDTH)-1);243 unsigned int y_cluster = (procid >> P_WIDTH) & ((1<<Y_WIDTH)-1);244 245 204 // compute index in PT1 246 205 unsigned int ix1 = vpn >> 9; // 11 bits for ix1 247 206 248 207 // get page table physical base address 249 paddr_t pt1_pbase = _ptabs_paddr[vspace_id][x][y]; 250 251 // check pt1_base 208 paddr_t pt1_pbase = _ptabs_paddr[vspace_id][x][y]; 209 252 210 if ( pt1_pbase == 0 ) 253 211 { 254 _get_lock(&lock_tty); 255 _puts("\n[BOOT ERROR] in boot_add_pte1() : illegal pbase address for PTAB["); 256 _putd( vspace_id ); 257 _puts(","); 258 _putd( x ); 259 _puts(","); 260 _putd( y ); 261 _puts("]"); 262 _puts(" in cluster["); 263 _putd(x_cluster); 264 _puts(","); 265 _putd(y_cluster); 266 _puts("]\n"); 267 _release_lock(&lock_tty); 212 _printf("\n[BOOT ERROR] in boot_add_pte1() : no PTAB in cluster[%d,%d]" 213 " containing processors\n", x , y ); 268 214 _exit(); 269 215 } … … 277 223 _physical_write( pt1_pbase + 4*ix1, pte1 ); 278 224 279 #if (BOOT_DEBUG_PT > 1 ) 280 _get_lock(&lock_tty); 281 _puts(" - Write pte1 "); 282 _putx( pte1 ); 283 _puts(" in paddr "); 284 _putl( pt1_pbase + 4*ix1 ); 285 _puts(" in cluster["); 286 _putd(x_cluster); 287 _puts(","); 288 _putd(y_cluster); 289 _puts("]\n"); 290 _puts("\n"); 291 _release_lock(&lock_tty); 292 #endif 225 asm volatile ("sync"); 293 226 294 227 } // end boot_add_pte1() … … 300 233 // As the set of PT2s is implemented as a fixed size array (no dynamic 301 234 // allocation), this function checks a possible overflow of the PT2 array. 235 // As a given entry in PT1 can be shared by several vsegs, mapped by 236 // different processors, we need to take the lock protecting PTAB[v][x]y]. 302 237 ////////////////////////////////////////////////////////////////////////////// 303 238 void boot_add_pte2( unsigned int vspace_id, … … 308 243 unsigned int ppn ) // 28 bits right-justified 309 244 { 310 311 #if (BOOT_DEBUG_PT > 1)312 _get_lock(&lock_tty);313 _puts(" - PTE2 in PTAB[");314 _putd( vspace_id );315 _puts(",");316 _putd( x );317 _puts(",");318 _putd( y );319 _puts("] : vpn = ");320 _putx( vpn );321 _puts(" / ppn = ");322 _putx( ppn );323 _puts(" / flags = ");324 _putx( flags );325 _puts("\n");326 _release_lock(&lock_tty);327 #endif328 329 245 unsigned int ix1; 330 246 unsigned int ix2; … … 337 253 ix2 = vpn & 0x1FF; // 9 bits for ix2 338 254 339 // get page table physical base address and size255 // get page table physical base address 340 256 paddr_t pt1_pbase = _ptabs_paddr[vspace_id][x][y]; 341 257 342 // check pt1_base343 258 if ( pt1_pbase == 0 ) 344 259 { 345 _get_lock(&lock_tty); 346 _puts("\n[BOOT ERROR] in boot_add_pte2() : PTAB["); 347 _putd( vspace_id ); 348 _puts(","); 349 _putd( x ); 350 _puts(","); 351 _putd( y ); 352 _puts("] undefined\n"); 353 _release_lock(&lock_tty); 260 _printf("\n[BOOT ERROR] in boot_add_pte2() : no PTAB for vspace %d " 261 "in cluster[%d,%d]\n", vspace_id , x , y ); 354 262 _exit(); 355 263 } 356 264 265 // get lock protecting PTAB[vspace_id][x][y] 266 _spin_lock_acquire( &_ptabs_spin_lock[vspace_id][x][y] ); 267 357 268 // get ptd in PT1 358 _get_lock(&lock_next_pt2[vspace_id][x][y]); 359 ptd = _physical_read(pt1_pbase + 4 * ix1); 269 ptd = _physical_read( pt1_pbase + 4 * ix1 ); 360 270 361 271 if ((ptd & PTE_V) == 0) // undefined PTD: compute PT2 base address, 362 272 // and set a new PTD in PT1 363 273 { 274 // get a new pt2_id 364 275 pt2_id = _ptabs_next_pt2[vspace_id][x][y]; 276 _ptabs_next_pt2[vspace_id][x][y] = pt2_id + 1; 277 278 // check overflow 365 279 if (pt2_id == _ptabs_max_pt2) 366 280 { 367 _puts("\n[BOOT ERROR] in boot_add_pte2() : PTAB["); 368 _putd( vspace_id ); 369 _puts(","); 370 _putd( x ); 371 _puts(","); 372 _putd( y ); 373 _puts("] contains not enough PT2s\n"); 281 _printf("\n[BOOT ERROR] in boot_add_pte2() : PTAB[%d,%d,%d]" 282 " contains not enough PT2s\n", vspace_id, x, y ); 374 283 _exit(); 375 284 } … … 377 286 pt2_pbase = pt1_pbase + PT1_SIZE + PT2_SIZE * pt2_id; 378 287 ptd = PTE_V | PTE_T | (unsigned int) (pt2_pbase >> 12); 288 289 // set PTD into PT1 379 290 _physical_write( pt1_pbase + 4*ix1, ptd); 380 _ptabs_next_pt2[vspace_id][x][y] = pt2_id + 1;381 291 } 382 292 else // valid PTD: compute PT2 base address … … 385 295 } 386 296 387 _release_lock(&lock_next_pt2[vspace_id][x][y]);388 297 // set PTE in PT2 : flags & PPN in two 32 bits words 389 298 pte2_paddr = pt2_pbase + 8 * ix2; 390 _physical_write(pte2_paddr , (PTE_V |flags) ); 391 _physical_write(pte2_paddr + 4 , ppn); 299 _physical_write(pte2_paddr , (PTE_V | flags) ); 300 _physical_write(pte2_paddr + 4 , ppn ); 301 302 // release lock protecting PTAB[vspace_id][x][y] 303 _spin_lock_release( &_ptabs_spin_lock[vspace_id][x][y] ); 304 305 asm volatile ("sync"); 392 306 393 307 } // end boot_add_pte2() … … 397 311 // defined by alignPow2 == L2(alignement). 398 312 //////////////////////////////////////////////////////////////////////////////////// 399 paddr_t paddr_align_to( paddr_t paddr, unsigned int alignPow2)313 paddr_t paddr_align_to( paddr_t paddr, unsigned int alignPow2 ) 400 314 { 401 315 paddr_t mask = (1 << alignPow2) - 1; … … 403 317 } 404 318 405 unsigned int vaddr_align_to( unsigned int vaddr, unsigned int alignPow2)319 unsigned int vaddr_align_to( unsigned int vaddr, unsigned int alignPow2 ) 406 320 { 407 321 unsigned int mask = (1 << alignPow2) - 1; … … 412 326 // This function map a vseg identified by the vseg pointer. 413 327 // 414 // A given vseg can be mapped in Big Physical Pages (BPP: 2 Mbytes) or in a328 // A given vseg can be mapped in a Big Physical Pages (BPP: 2 Mbytes) or in a 415 329 // Small Physical Pages (SPP: 4 Kbytes), depending on the "big" attribute of vseg, 416 330 // with the following rules: … … 424 338 // account the alignment constraints and register it in vobj->vbase field. 425 339 // 426 // 2) Second step: it allocates the required number of physical pages,340 // 2) Second step: it allocates the required number of contiguous physical pages, 427 341 // computes the physical base address (if the vseg is not identity mapping), 428 342 // and register it in the vseg pbase field. 429 // Only the 4vsegs used by the boot code and the peripheral vsegs430 // can be identity mapping :The first big physical page in cluster[0,0]431 // is reserved for the 4boot vsegs.343 // Only the vsegs used by the boot code and the peripheral vsegs 344 // can be identity mapping. The first big physical page in cluster[0,0] 345 // is reserved for the boot vsegs. 432 346 // 433 // 3) Third step (only for vseg that have the VOBJ_TYPE_PTAB): allpage tables434 // associated to the variousvspaces must be packed in the same vseg.435 // We divide th evseg in M sub-segments, and compute the vbase and pbase436 // addresses for each page table, and register itin the _ptabs_paddr347 // 3) Third step (only for vseg that have the VOBJ_TYPE_PTAB): the M page tables 348 // associated to the M vspaces must be packed in the same vseg. 349 // We divide this vseg in M sub-segments, and compute the vbase and pbase 350 // addresses for M page tables, and register these addresses in the _ptabs_paddr 437 351 // and _ptabs_vaddr arrays. 438 352 // … … 496 410 //////////// - if vseg is ram : ppn <= physical memory allocator 497 411 498 unsigned int ppn; // first physical page index ( 28 bits = |x|y|bppi|sppi|)499 unsigned int vpn; // first virtual page index ( 20 bits = |ix1|ix2|)500 unsigned int vpn_max; // last virtual page index ( 20 bits = |ix1|ix2|)412 unsigned int ppn; // first physical page index (28 bits = |x|y|bppi|sppi|) 413 unsigned int vpn; // first virtual page index (20 bits = |ix1|ix2|) 414 unsigned int vpn_max; // last virtual page index (20 bits = |ix1|ix2|) 501 415 502 416 vpn = vseg->vbase >> 12; … … 539 453 paddr_t paddr = _ptabs_paddr[vsid][x_dest][y_dest] + (ix1<<2); 540 454 unsigned int pte1 = _physical_read( paddr ); 541 #if (BOOT_DEBUG_PT > 1) 542 _get_lock(&lock_tty); 543 _puts("[BOOT DEBUG] "); 544 _puts( vseg->name ); 545 _puts(" in cluster["); 546 _putd( x_dest ); 547 _puts(","); 548 _putd( y_dest ); 549 _puts("] : vbase = "); 550 _putx( vseg->vbase ); 551 _puts(" / paddr = "); 552 _putl( paddr ); 553 _puts(" / pte1 = "); 554 _putx( pte1 ); 555 _puts(" by processor "); 556 _putd(_get_procid()); 557 _puts("\n"); 558 _release_lock(&lock_tty); 559 #endif 455 560 456 if ( (pte1 & PTE_V) == 0 ) // BPP not allocated yet 561 457 { … … 572 468 if (pte1 & PTE_W) pte1_mode |= W_MODE_MASK; 573 469 if (pte1 & PTE_U) pte1_mode |= U_MODE_MASK; 574 if (vseg->mode != pte1_mode) { 575 _puts("\n[BOOT ERROR] in boot_vseg_map() : vseg "); 576 _puts( vseg->name ); 577 _puts(" has different flags ("); 578 _putx( vseg->mode ); 579 _puts(") than other vsegs sharing the same big page ("); 580 _putx( pte1_mode ); 581 _puts(")"); 470 if (vseg->mode != pte1_mode) 471 { 472 _printf("\n[BOOT ERROR] in boot_vseg_map() : " 473 "vseg %s has different flags than another vseg " 474 "in the same BPP\n", vseg->name ); 582 475 _exit(); 583 476 } 584 585 477 ppn = ((pte1 << 9) & 0x0FFFFE00); 586 478 } … … 597 489 // update vseg.pbase field and update vsegs chaining 598 490 vseg->pbase = ((paddr_t)ppn) << 12; 491 vseg->mapped = 1; 599 492 vseg->next_vseg = pseg->next_vseg; 600 493 pseg->next_vseg = (unsigned int)vseg; … … 637 530 } 638 531 532 asm volatile ("sync"); 533 639 534 #if BOOT_DEBUG_PT 640 _get_lock(&lock_tty); 641 _puts("[BOOT DEBUG] "); 642 _puts( vseg->name ); 643 _puts(" in cluster["); 644 _putd( x_dest ); 645 _puts(","); 646 _putd( y_dest ); 647 _puts("] : vbase = "); 648 _putx( vseg->vbase ); 649 _puts(" / length = "); 650 _putx( vseg->length ); 651 if ( big ) _puts(" / BIG / npages = "); 652 else _puts(" / SMALL / npages = "); 653 _putd( npages ); 654 _puts(" / pbase = "); 655 _putl( vseg->pbase ); 656 _puts("\n"); 657 _release_lock(&lock_tty); 535 if ( big ) 536 _printf("\n[BOOT] vseg %s : cluster[%d,%d] / " 537 "vbase = %x / length = %x / BIG / npages = %d / pbase = %l\n", 538 vseg->name, x_dest, y_dest, vseg->vbase, vseg->length, npages, vseg-> pbase ); 539 else 540 _printf("\n[BOOT] vseg %s : cluster[%d,%d] / " 541 "vbase = %x / length = %x / SMALL / npages = %d / pbase = %l\n", 542 vseg->name, x_dest, y_dest, vseg->vbase, vseg->length, npages, vseg-> pbase ); 658 543 #endif 659 544 … … 661 546 662 547 ///////////////////////////////////////////////////////////////////////////////////// 663 // For the vseg defined by the vseg pointer, this function register allPTEs548 // For the vseg defined by the vseg pointer, this function register PTEs 664 549 // in one or several page tables. 665 550 // It is a global vseg (kernel vseg) if (vspace_id == 0xFFFFFFFF). 666 551 // The number of involved PTABs depends on the "local" and "global" attributes: 667 552 // - PTEs are replicated in all vspaces for a global vseg. 668 // - PTEs are replicated in all clusters for a non local vseg.553 // - PTEs are replicated in all clusters containing procs for a non local vseg. 669 554 ///////////////////////////////////////////////////////////////////////////////////// 670 555 void boot_vseg_pte( mapping_vseg_t* vseg, … … 690 575 691 576 // compute vseg flags 692 // The three flags (Local, Remote and Dirty) are set to 1 to reduce693 // latency of TLB miss (L/R) and write (D): Avoid hardware update694 // mechanism for these flags because GIET_VMdoes use these flags.577 // The three flags (Local, Remote and Dirty) are set to 1 578 // to avoid hardware update for these flags, because GIET_VM 579 // does use these flags. 695 580 unsigned int flags = 0; 696 581 if (vseg->mode & C_MODE_MASK) flags |= PTE_C; … … 711 596 else npages = (vpn_max>>9) - (vpn>>9) + 1; 712 597 713 // compute destination cluster coordinates 714 unsigned int x_dest; 715 unsigned int y_dest; 716 mapping_header_t* header = (mapping_header_t *)SEG_BOOT_MAPPING_BASE; 717 mapping_cluster_t* cluster = _get_cluster_base(header); 718 mapping_pseg_t* pseg = _get_pseg_base(header); 719 pseg = pseg + vseg->psegid; 720 cluster = cluster + pseg->clusterid; 721 x_dest = cluster->x; 722 y_dest = cluster->y; 723 724 unsigned int p; // iterator for physical page index 725 unsigned int x; // iterator for cluster x coordinate 726 unsigned int y; // iterator for cluster y coordinate 727 unsigned int v; // iterator for vspace index 598 // compute destination cluster coordinates, for local vsegs 599 mapping_header_t* header = (mapping_header_t *)SEG_BOOT_MAPPING_BASE; 600 mapping_cluster_t* cluster = _get_cluster_base(header); 601 mapping_pseg_t* pseg = _get_pseg_base(header); 602 mapping_pseg_t* pseg_dest = &pseg[vseg->psegid]; 603 mapping_cluster_t* cluster_dest = &cluster[pseg_dest->clusterid]; 604 unsigned int x_dest = cluster_dest->x; 605 unsigned int y_dest = cluster_dest->y; 606 607 unsigned int p; // iterator for physical page index 608 unsigned int x; // iterator for cluster x coordinate 609 unsigned int y; // iterator for cluster y coordinate 610 unsigned int v; // iterator for vspace index 728 611 729 612 // loop on PTEs … … 757 640 for ( y = 0 ; y < Y_SIZE ; y++ ) 758 641 { 759 if ( big ) // big pages => PTE1s642 if ( cluster[(x * Y_SIZE) + y].procs ) 760 643 { 761 boot_add_pte1( vsid, 762 x, 763 y, 764 vpn + (p<<9), 765 flags, 766 ppn + (p<<9) ); 767 } 768 else // small pages => PTE2s 769 { 770 boot_add_pte2( vsid, 771 x, 772 y, 773 vpn + p, 774 flags, 775 ppn + p ); 644 if ( big ) // big pages => PTE1s 645 { 646 boot_add_pte1( vsid, 647 x, 648 y, 649 vpn + (p<<9), 650 flags, 651 ppn + (p<<9) ); 652 } 653 else // small pages => PTE2s 654 { 655 boot_add_pte2( vsid, 656 x, 657 y, 658 vpn + p, 659 flags, 660 ppn + p ); 661 } 776 662 } 777 663 } … … 808 694 for ( y = 0 ; y < Y_SIZE ; y++ ) 809 695 { 810 for ( v = 0 ; v < header->vspaces ; v++)696 if ( cluster[(x * Y_SIZE) + y].procs ) 811 697 { 812 if ( big ) // big pages => PTE1s698 for ( v = 0 ; v < header->vspaces ; v++ ) 813 699 { 814 boot_add_pte1( v, 815 x, 816 y, 817 vpn + (p<<9), 818 flags, 819 ppn + (p<<9) ); 820 } 821 else // small pages -> PTE2s 822 { 823 boot_add_pte2( v, 824 x, 825 y, 826 vpn + p, 827 flags, 828 ppn + p ); 700 if ( big ) // big pages => PTE1s 701 { 702 boot_add_pte1( v, 703 x, 704 y, 705 vpn + (p<<9), 706 flags, 707 ppn + (p<<9) ); 708 } 709 else // small pages -> PTE2s 710 { 711 boot_add_pte2( v, 712 x, 713 y, 714 vpn + p, 715 flags, 716 ppn + p ); 717 } 829 718 } 830 719 } … … 833 722 } 834 723 } // end for pages 724 725 asm volatile ("sync"); 726 835 727 } // end boot_vseg_pte() 836 728 729 837 730 /////////////////////////////////////////////////////////////////////////////// 838 // This function initialises the page tables for all vspaces defined 839 // in the mapping_info data structure. 840 // For each vspace, there is one page table per cluster. 731 // Processor P[x][y][0] computes physical base address for all globals vsegs, 732 // using the local Page Table, to check page tables initialisation. 733 /////////////////////////////////////////////////////////////////////////////// 734 void boot_ptab_check( unsigned int x, 735 unsigned int y ) 736 { 737 mapping_header_t* header = (mapping_header_t *)SEG_BOOT_MAPPING_BASE; 738 mapping_vseg_t* vseg = _get_vseg_base(header); 739 page_table_t* ptab = (page_table_t*)_ptabs_vaddr[0][x][y]; 740 741 unsigned int vseg_id; 742 for (vseg_id = 0; vseg_id < header->globals; vseg_id++) 743 { 744 unsigned int vpn = vseg[vseg_id].vbase >> 12; 745 unsigned int ppn = 0; 746 unsigned int flags = 0; 747 _v2p_translate( ptab , vpn , &ppn , &flags ); 748 _printf("@@@ P[%d,%d,0] access vseg %s : vpn = %x / ppn = %x\n", 749 x , y , vseg[vseg_id].name , vpn , ppn ); 750 } 751 } 752 753 /////////////////////////////////////////////////////////////////////////////// 754 // This function is executed by processor[x][y][0] in each cluster 755 // containing at least one processor. 756 // It initialises all page table for all global or private vsegs 757 // mapped in cluster[x][y], as specified in the mapping. 841 758 // In each cluster all page tables for the different vspaces must be 842 759 // packed in one vseg occupying one single BPP (Big Physical Page). 843 760 // 844 // This fonction is executed by the processor[x][y][0], the vsegs mapped in the845 // cluster[x][y] in map.bin file are handled by the processor[x][y][0]846 //847 761 // For each vseg, the mapping is done in two steps: 848 762 // 1) mapping : the boot_vseg_map() function allocates contiguous BPPs 849 763 // or SPPs (if the vseg is not associated to a peripheral), and register 850 764 // the physical base address in the vseg pbase field. It initialises the 851 // _ptabs_vaddr and _ptabs_paddrarrays if the vseg is a PTAB.765 // _ptabs_vaddr[] and _ptabs_paddr[] arrays if the vseg is a PTAB. 852 766 // 853 767 // 2) page table initialisation : the boot_vseg_pte() function initialise … … 857 771 // 858 772 // We must handle vsegs in the following order 859 // 1) all global vsegs containing a page table,860 // 2) all global vsegs occupying more than one BPP,861 // 3) all others global vsegs862 // 4) all private vsegs in user space.773 // 1) global vseg containing PTAB mapped in cluster[x][y], 774 // 2) global vsegs occupying more than one BPP mapped in cluster[x][y], 775 // 3) others global vsegs mapped in cluster[x][y], 776 // 4) all private vsegs in all user spaces mapped in cluster[x][y]. 863 777 /////////////////////////////////////////////////////////////////////////////// 864 void boot_ptabs_init() 778 void boot_ptab_init( unsigned int cx, 779 unsigned int cy ) 865 780 { 866 781 mapping_header_t* header = (mapping_header_t *)SEG_BOOT_MAPPING_BASE; … … 875 790 876 791 unsigned int procid = _get_procid(); 877 unsigned int x_cluster = (procid >> (Y_WIDTH + P_WIDTH)) & ((1<<X_WIDTH)-1);878 unsigned int y_cluster = (procid >> P_WIDTH) & ((1<<Y_WIDTH)-1);879 792 unsigned int lpid = procid & ((1<<P_WIDTH)-1); 880 793 881 if(lpid) 882 { 883 _puts("[BOOT ERROR] boot_ptabs_init() : error local processor id\n"); 794 if( lpid ) 795 { 796 _printf("\n[BOOT ERROR] in boot_ptab_init() : " 797 "P[%d][%d][%d] should not execute it\n", cx, cy, lpid ); 884 798 _exit(); 885 799 } 886 800 887 if (header->vspaces == 0 ) 888 { 889 _puts("\n[BOOT ERROR] in boot_ptabs_init() : mapping "); 890 _puts( header->name ); 891 _puts(" contains no vspace\n"); 801 if ( header->vspaces == 0 ) 802 { 803 _printf("\n[BOOT ERROR] in boot_ptab_init() : " 804 "mapping %s contains no vspace\n", header->name ); 892 805 _exit(); 893 806 } 894 807 895 ///////// Phase 1 : global vsegs containing a PTAB (two loops required) 896 897 #if BOOT_DEBUG_PT 898 _get_lock(&lock_tty); 899 _puts("\n[BOOT DEBUG] map PTAB global vsegs in cluster["); 900 _putd(x_cluster); 901 _puts(","); 902 _putd(y_cluster); 903 _puts("]"); 904 _puts("\n"); 905 _release_lock(&lock_tty); 906 #endif 907 808 ///////// Phase 1 : global vseg containing the PTAB (two barriers required) 809 810 // get local PTAB vseg 811 unsigned int found = 0; 908 812 for (vseg_id = 0; vseg_id < header->globals; vseg_id++) 909 813 { … … 912 816 cluster = _get_cluster_base(header) + pseg->clusterid; 913 817 if ( (vobj[vobj_id].type == VOBJ_TYPE_PTAB) && 914 (cluster->x == x_cluster) && 915 (cluster->y == y_cluster)) 916 { 917 boot_vseg_map( &vseg[vseg_id], 0xFFFFFFFF ); 918 vseg[vseg_id].mapped = 1; 919 } 920 } 921 922 _barrier_wait(&barrier_boot); 923 924 for (vseg_id = 0; vseg_id < header->globals; vseg_id++) 925 { 926 unsigned int vobj_id = vseg[vseg_id].vobj_offset; 927 pseg = _get_pseg_base(header) + vseg[vseg_id].psegid; 928 cluster = _get_cluster_base(header) + pseg->clusterid; 929 if ( (vobj[vobj_id].type == VOBJ_TYPE_PTAB) && 930 (cluster->x == x_cluster) && 931 (cluster->y == y_cluster)) 932 { 933 boot_vseg_pte( &vseg[vseg_id], 0xFFFFFFFF ); 934 vseg[vseg_id].mapped = 1; 935 } 936 } 937 938 _barrier_wait(&barrier_boot); 939 940 ///////// Phase 2 : global vsegs occupying more than one BPP (one loop) 941 942 #if BOOT_DEBUG_PT 943 _get_lock(&lock_tty); 944 _puts("\n[BOOT DEBUG] map all multi-BPP global vseg in cluster["); 945 _putd(x_cluster); 946 _puts(","); 947 _putd(y_cluster); 948 _puts("]"); 949 _puts("\n"); 950 _release_lock(&lock_tty); 951 #endif 818 (cluster->x == cx) && (cluster->y == cy) ) 819 { 820 found = 1; 821 break; 822 } 823 } 824 if ( found == 0 ) 825 { 826 _printf("\n[BOOT ERROR] in boot_ptab_init() : " 827 "cluster[%d][%d] contains no PTAB vseg\n", cx , cy ); 828 _exit(); 829 } 830 831 boot_vseg_map( &vseg[vseg_id], 0xFFFFFFFF ); 832 833 ////////////////////////////////////////////// 834 _simple_barrier_wait( &_barrier_all_clusters ); 835 ////////////////////////////////////////////// 836 837 boot_vseg_pte( &vseg[vseg_id], 0xFFFFFFFF ); 838 839 ////////////////////////////////////////////// 840 _simple_barrier_wait( &_barrier_all_clusters ); 841 ////////////////////////////////////////////// 842 843 ///////// Phase 2 : global vsegs occupying more than one BPP 952 844 953 845 for (vseg_id = 0; vseg_id < header->globals; vseg_id++) … … 958 850 if ( (vobj[vobj_id].length > 0x200000) && 959 851 (vseg[vseg_id].mapped == 0) && 960 (cluster->x == x_cluster) && 961 (cluster->y == y_cluster)) 852 (cluster->x == cx) && (cluster->y == cy) ) 962 853 { 963 854 boot_vseg_map( &vseg[vseg_id], 0xFFFFFFFF ); 964 vseg[vseg_id].mapped = 1;965 855 boot_vseg_pte( &vseg[vseg_id], 0xFFFFFFFF ); 966 856 } 967 857 } 968 858 969 ///////// Phase 3 : all others global vsegs (one loop) 970 971 #if BOOT_DEBUG_PT 972 _get_lock(&lock_tty); 973 _puts("\n[BOOT DEBUG] map all others global in cluster[ "); 974 _putd(x_cluster); 975 _puts(","); 976 _putd(y_cluster); 977 _puts("]"); 978 _puts("\n"); 979 _release_lock(&lock_tty); 980 #endif 859 ///////// Phase 3 : all others global vsegs 981 860 982 861 for (vseg_id = 0; vseg_id < header->globals; vseg_id++) 983 { 984 unsigned int vobj_id = vseg[vseg_id].vobj_offset; 862 { 985 863 pseg = _get_pseg_base(header) + vseg[vseg_id].psegid; 986 864 cluster = _get_cluster_base(header) + pseg->clusterid; 987 if ( (vobj[vobj_id].length <= 0x200000) && 988 (vseg[vseg_id].mapped == 0) && 989 (cluster->x == x_cluster) && 990 (cluster->y == y_cluster)) 865 if ( (vseg[vseg_id].mapped == 0) && 866 (cluster->x == cx) && (cluster->y == cy) ) 991 867 { 992 868 boot_vseg_map( &vseg[vseg_id], 0xFFFFFFFF ); 993 vseg[vseg_id].mapped = 1;994 869 boot_vseg_pte( &vseg[vseg_id], 0xFFFFFFFF ); 995 870 } 996 871 } 997 872 998 ///////// Phase 4 : all private vsegs (two nested loops)873 ///////// Phase 4 : all private vsegs 999 874 1000 875 for (vspace_id = 0; vspace_id < header->vspaces; vspace_id++) 1001 876 { 1002 1003 #if BOOT_DEBUG_PT1004 _get_lock(&lock_tty);1005 _puts("\n[BOOT DEBUG] map private vsegs for vspace ");1006 _puts( vspace[vspace_id].name );1007 _puts(" in cluster[ ");1008 _putd(x_cluster);1009 _puts(",");1010 _putd(y_cluster);1011 _puts("]");1012 _puts("\n");1013 _release_lock(&lock_tty);1014 #endif1015 1016 877 for (vseg_id = vspace[vspace_id].vseg_offset; 1017 878 vseg_id < (vspace[vspace_id].vseg_offset + vspace[vspace_id].vsegs); … … 1020 881 pseg = _get_pseg_base(header) + vseg[vseg_id].psegid; 1021 882 cluster = _get_cluster_base(header) + pseg->clusterid; 1022 if((vseg[vseg_id].mapped == 0) && 1023 (cluster->x == x_cluster) && 1024 (cluster->y == y_cluster)) 883 if ( (cluster->x == cx) && (cluster->y == cy) ) 1025 884 { 1026 885 boot_vseg_map( &vseg[vseg_id], vspace_id ); 1027 vseg[vseg_id].mapped = 1;1028 886 boot_vseg_pte( &vseg[vseg_id], vspace_id ); 1029 887 } … … 1031 889 } 1032 890 1033 #if (BOOT_DEBUG_PT > 2) 1034 _get_lock(&lock_tty); 1035 mapping_vseg_t* curr; 1036 mapping_pseg_t* pseg = _get_pseg_base(header); 1037 mapping_cluster_t* cluster = _get_cluster_base(header); 1038 unsigned int pseg_id; 1039 for( pseg_id = 0 ; pseg_id < header->psegs ; pseg_id++ ) 891 ////////////////////////////////////////////// 892 _simple_barrier_wait( &_barrier_all_clusters ); 893 ////////////////////////////////////////////// 894 895 } // end boot_ptab_init() 896 897 //////////////////////////////////////////////////////////////////////////////// 898 // This function should be executed by P[0][0][0] only. It complete the 899 // page table initialisation, taking care of all global vsegs that are 900 // not mapped in a cluster containing a processor, and have not been 901 // handled by the boot_ptab_init(x,y) function. 902 // An example of such vsegs are the external peripherals in TSAR_LETI platform. 903 //////////////////////////////////////////////////////////////////////////////// 904 void boot_ptab_extend() 1040 905 { 1041 unsigned int cluster_id = pseg[pseg_id].clusterid; 1042 _puts("\n[BOOT DEBUG] vsegs mapped on pseg "); 1043 _puts( pseg[pseg_id].name ); 1044 _puts(" in cluster["); 1045 _putd( cluster[cluster_id].x ); 1046 _puts(","); 1047 _putd( cluster[cluster_id].y ); 1048 _puts("]\n"); 1049 for( curr = (mapping_vseg_t*)pseg[pseg_id].next_vseg ; 1050 curr != 0 ; 1051 curr = (mapping_vseg_t*)curr->next_vseg ) 1052 { 1053 _puts(" - vseg "); 1054 _puts( curr->name ); 1055 _puts(" : len = "); 1056 _putx( curr->length ); 1057 _puts(" / vbase "); 1058 _putx( curr->vbase ); 1059 _puts(" / pbase "); 1060 _putl( curr->pbase ); 1061 _puts("\n"); 1062 } 1063 } 1064 _release_lock(&lock_tty); 1065 #endif 1066 1067 } // end boot_ptabs_init() 1068 1069 /////////////////////////////////////////////////////////////////////////////// 1070 // This function initializes the private vobjs that have the CONST type. 1071 // The MMU is supposed to be activated... 1072 /////////////////////////////////////////////////////////////////////////////// 1073 void boot_vobjs_init() 1074 { 1075 mapping_header_t* header = (mapping_header_t *)SEG_BOOT_MAPPING_BASE; 1076 mapping_vspace_t* vspace = _get_vspace_base(header); 1077 mapping_vobj_t* vobj = _get_vobj_base(header); 1078 1079 unsigned int vspace_id; 1080 unsigned int vobj_id; 1081 1082 // loop on the vspaces 1083 for (vspace_id = 0; vspace_id < header->vspaces; vspace_id++) 1084 { 1085 1086 #if BOOT_DEBUG_VOBJS 1087 _puts("\n[BOOT DEBUG] ****** vobjs initialisation in vspace "); 1088 _puts(vspace[vspace_id].name); 1089 _puts(" ******\n"); 1090 #endif 1091 1092 _set_mmu_ptpr( (unsigned int)(_ptabs_paddr[vspace_id][0][0] >> 13) ); 1093 1094 // loop on the vobjs 1095 for (vobj_id = vspace[vspace_id].vobj_offset; 1096 vobj_id < (vspace[vspace_id].vobj_offset + vspace[vspace_id].vobjs); 1097 vobj_id++) 1098 { 1099 if ( (vobj[vobj_id].type) == VOBJ_TYPE_CONST ) 1100 { 1101 #if BOOT_DEBUG_VOBJS 1102 _puts("CONST : "); 1103 _puts(vobj[vobj_id].name); 1104 _puts(" / vaddr = "); 1105 _putx(vobj[vobj_id].vaddr); 1106 _puts(" / paddr = "); 1107 _putl(vobj[vobj_id].paddr); 1108 _puts(" / value = "); 1109 _putx(vobj[vobj_id].init); 1110 _puts("\n"); 1111 #endif 1112 unsigned int* addr = (unsigned int *) vobj[vobj_id].vbase; 1113 *addr = vobj[vobj_id].init; 1114 } 1115 } 1116 } 1117 } // end boot_vobjs_init() 906 907 mapping_header_t* header = (mapping_header_t *)SEG_BOOT_MAPPING_BASE; 908 mapping_vseg_t* vseg = _get_vseg_base(header); 909 910 unsigned int vseg_id; 911 912 for (vseg_id = 0; vseg_id < header->globals; vseg_id++) 913 { 914 if ( vseg[vseg_id].mapped == 0 ) 915 { 916 boot_vseg_map( &vseg[vseg_id], 0xFFFFFFFF ); 917 boot_vseg_pte( &vseg[vseg_id], 0xFFFFFFFF ); 918 } 919 } 920 } // end boot_ptab_extend() 1118 921 1119 922 /////////////////////////////////////////////////////////////////////////////// … … 1147 950 { 1148 951 mapping_cluster_t* cluster = _get_cluster_base(header); 1149 _puts("\n[BOOT ERROR] No vobj of type SCHED in cluster ["); 1150 _putd( cluster[cluster_id].x ); 1151 _puts(","); 1152 _putd( cluster[cluster_id].y ); 1153 _puts("]\n"); 952 _printf("\n[BOOT ERROR] No vobj of type SCHED in cluster [%d,%d]\n", 953 cluster[cluster_id].x, cluster[cluster_id].y ); 1154 954 _exit(); 1155 955 } … … 1157 957 1158 958 //////////////////////////////////////////////////////////////////////////////////// 1159 // This function i nitialises all processors schedulers.1160 // This is done by processor 0, and the MMU must be activated.1161 // - In Step 1, it initialises the _schedulers[x][y][l] pointers array, and scan1162 // the processors for a first initialisation of the schedulers:1163 // idle_task context, and HWI / SWI / PTI vectors.959 // This function is executed in parallel by all processors P[x][y][0]. 960 // It initialises all schedulers in cluster [x][y]. The MMU must be activated. 961 // It is split in two phases separated by a synchronisation barrier. 962 // - In Step 1, it initialises the _schedulers[x][y][l] pointers array, 963 // the idle_task context and the HWI / PTI vectors. 1164 964 // - In Step 2, it scan all tasks in all vspaces to complete the tasks contexts, 1165 // initialisation as specified in the mapping_info data structure. 965 // initialisation as specified in the mapping_info data structure, 966 // and set the CP0_SCHED register. 1166 967 //////////////////////////////////////////////////////////////////////////////////// 1167 void boot_schedulers_init() 968 void boot_scheduler_init( unsigned int x, 969 unsigned int y ) 1168 970 { 1169 mapping_header_t* header = (mapping_header_t *)SEG_BOOT_MAPPING_BASE; 1170 mapping_cluster_t* cluster = _get_cluster_base(header); 1171 mapping_vspace_t* vspace = _get_vspace_base(header); 1172 mapping_task_t* task = _get_task_base(header); 1173 mapping_vobj_t* vobj = _get_vobj_base(header); 1174 mapping_periph_t* periph = _get_periph_base(header); 1175 mapping_irq_t* irq = _get_irq_base(header); 1176 1177 unsigned int cluster_id; // cluster index in mapping_info 1178 unsigned int periph_id; // peripheral index in mapping_info 1179 unsigned int irq_id; // irq index in mapping_info 1180 unsigned int vspace_id; // vspace index in mapping_info 1181 unsigned int task_id; // task index in mapping_info 1182 unsigned int vobj_id; // vobj index in mapping_info 1183 1184 unsigned int lpid; // local processor index (for several loops) 1185 1186 // WTI allocators to processors (for HWIs translated to WTIs) 1187 // In all clusters the first NB_PROCS_MAX WTIs are reserved for WAKUP 1188 unsigned int alloc_wti_channel[X_SIZE*Y_SIZE]; // one per cluster 1189 1190 // pointers on the XCU and PIC peripherals 971 mapping_header_t* header = (mapping_header_t *)SEG_BOOT_MAPPING_BASE; 972 mapping_cluster_t* cluster = _get_cluster_base(header); 973 mapping_vspace_t* vspace = _get_vspace_base(header); 974 mapping_task_t* task = _get_task_base(header); 975 mapping_vobj_t* vobj = _get_vobj_base(header); 976 mapping_periph_t* periph = _get_periph_base(header); 977 mapping_irq_t* irq = _get_irq_base(header); 978 979 unsigned int periph_id; 980 unsigned int irq_id; 981 unsigned int vspace_id; 982 unsigned int task_id; 983 unsigned int vobj_id; 984 985 unsigned int sched_vbase; // schedulers array vbase address 986 unsigned int sched_length; // schedulers array length 987 static_scheduler_t* psched; // pointer on processor scheduler 988 989 unsigned int cluster_id = x * Y_SIZE + y; 990 unsigned int nprocs = cluster[cluster_id].procs; 991 unsigned int lpid; 992 993 ///////////////////////////////////////////////////////////////////////// 994 // Step 1 : initialize the schedulers[] array of pointers, 995 // the idle task context and the HWI and PTI interrupt vectors. 996 // The WTI interrupt vector entries corresponding to interrupts 997 // generated by the PIC component are handled later. 998 999 // get scheduler array virtual base address in cluster[x,y] 1000 boot_get_sched_vaddr( cluster_id, &sched_vbase, &sched_length ); 1001 1002 if ( sched_length < (nprocs<<13) ) // 8 Kbytes per scheduler 1003 { 1004 _printf("\n[BOOT ERROR] Sched segment too small in cluster[%d,%d]\n", x, y ); 1005 _exit(); 1006 } 1007 1008 // loop on local processors 1009 for ( lpid = 0 ; lpid < nprocs ; lpid++ ) 1010 { 1011 // get scheduler pointer and initialise the schedulers pointers array 1012 psched = (static_scheduler_t*)(sched_vbase + (lpid<<13)); 1013 _schedulers[x][y][lpid] = psched; 1014 1015 // initialise the "tasks" and "current" variables default values 1016 psched->tasks = 0; 1017 psched->current = IDLE_TASK_INDEX; 1018 1019 // default values for HWI / PTI / SWI vectors (valid bit = 0) 1020 unsigned int slot; 1021 for (slot = 0; slot < 32; slot++) 1022 { 1023 psched->hwi_vector[slot] = 0; 1024 psched->pti_vector[slot] = 0; 1025 psched->wti_vector[slot] = 0; 1026 } 1027 1028 // WTI[lpid] <= ISR_WAKUP / PTI[lpid] <= ISR_TICK 1029 psched->wti_vector[lpid] = ISR_WAKUP | 0x80000000; 1030 psched->pti_vector[lpid] = ISR_TICK | 0x80000000; 1031 1032 // initializes the idle_task context: 1033 // - the SR slot is 0xFF03 because this task run in kernel mode. 1034 // - it uses the page table of vspace[0] 1035 // - it uses the kernel TTY terminal 1036 // - slots containing addresses (SP,RA,EPC) are initialised by kernel_init() 1037 1038 psched->context[IDLE_TASK_INDEX][CTX_CR_ID] = 0; 1039 psched->context[IDLE_TASK_INDEX][CTX_SR_ID] = 0xFF03; 1040 psched->context[IDLE_TASK_INDEX][CTX_PTPR_ID] = _ptabs_paddr[0][x][y]>>13; 1041 psched->context[IDLE_TASK_INDEX][CTX_PTAB_ID] = _ptabs_vaddr[0][x][y]; 1042 psched->context[IDLE_TASK_INDEX][CTX_TTY_ID] = 0; 1043 psched->context[IDLE_TASK_INDEX][CTX_LTID_ID] = IDLE_TASK_INDEX; 1044 psched->context[IDLE_TASK_INDEX][CTX_VSID_ID] = 0; 1045 psched->context[IDLE_TASK_INDEX][CTX_RUN_ID] = 1; 1046 } 1047 1048 // scan local peripherals to get local XCU 1191 1049 mapping_periph_t* xcu = NULL; 1192 mapping_periph_t* pic = NULL; 1193 1194 unsigned int sched_vbase; // schedulers array vbase address in a cluster 1195 unsigned int sched_length; // schedulers array length 1196 static_scheduler_t* psched; // pointer on processor scheduler 1197 1198 ///////////////////////////////////////////////////////////////////////// 1199 // Step 1 : loop on the clusters and on the processors 1200 // to initialize the schedulers[] array of pointers, 1201 // idle task context and interrupt vectors. 1202 // Implementation note: 1203 // We need to use both (proc_id) to scan the mapping info structure, 1204 // and (x,y,lpid) to access the schedulers array. 1205 1206 for (cluster_id = 0 ; cluster_id < X_SIZE*Y_SIZE ; cluster_id++) 1207 { 1208 unsigned int x = cluster[cluster_id].x; 1209 unsigned int y = cluster[cluster_id].y; 1210 1211 #if BOOT_DEBUG_SCHED 1212 _puts("\n[BOOT DEBUG] Initialise schedulers in cluster["); 1213 _putd( x ); 1214 _puts(","); 1215 _putd( y ); 1216 _puts("]\n"); 1217 #endif 1218 alloc_wti_channel[cluster_id] = NB_PROCS_MAX; 1219 1220 // checking processors number 1221 if ( cluster[cluster_id].procs > NB_PROCS_MAX ) 1222 { 1223 _puts("\n[BOOT ERROR] Too much processors in cluster["); 1224 _putd( x ); 1225 _puts(","); 1226 _putd( y ); 1227 _puts("]\n"); 1228 _exit(); 1229 } 1230 1231 // no schedulers initialisation if nprocs == 0 1232 if ( cluster[cluster_id].procs > 0 ) 1233 { 1234 // get scheduler array virtual base address in cluster[cluster_id] 1235 boot_get_sched_vaddr( cluster_id, &sched_vbase, &sched_length ); 1236 1237 if ( sched_length < (cluster[cluster_id].procs<<13) ) // 8 Kbytes per scheduler 1050 1051 for ( periph_id = cluster[cluster_id].periph_offset ; 1052 periph_id < cluster[cluster_id].periph_offset + cluster[cluster_id].periphs; 1053 periph_id++ ) 1054 { 1055 if( periph[periph_id].type == PERIPH_TYPE_XCU ) 1056 { 1057 xcu = &periph[periph_id]; 1058 1059 if ( xcu->arg < (nprocs * header->irq_per_proc) ) 1238 1060 { 1239 _puts("\n[BOOT ERROR] Schedulers segment too small in cluster["); 1240 _putd( x ); 1241 _puts(","); 1242 _putd( y ); 1243 _puts("]\n"); 1061 _printf("\n[BOOT ERROR] Not enough inputs for XCU[%d,%d]\n", x, y ); 1244 1062 _exit(); 1245 1063 } 1246 1247 // scan peripherals to find the XCU and the PIC component 1248 1249 xcu = NULL; 1250 for ( periph_id = cluster[cluster_id].periph_offset ; 1251 periph_id < cluster[cluster_id].periph_offset + cluster[cluster_id].periphs; 1252 periph_id++ ) 1253 { 1254 if( periph[periph_id].type == PERIPH_TYPE_XCU ) 1255 { 1256 xcu = &periph[periph_id]; 1257 1258 if ( xcu->arg < cluster[cluster_id].procs ) 1259 { 1260 _puts("\n[BOOT ERROR] Not enough inputs for XCU["); 1261 _putd( x ); 1262 _puts(","); 1263 _putd( y ); 1264 _puts("]\n"); 1265 _exit(); 1266 } 1267 } 1268 if( periph[periph_id].type == PERIPH_TYPE_PIC ) 1269 { 1270 pic = &periph[periph_id]; 1271 } 1272 } 1273 if ( xcu == NULL ) 1274 { 1275 _puts("\n[BOOT ERROR] No XCU component in cluster["); 1276 _putd( x ); 1277 _puts(","); 1278 _putd( y ); 1279 _puts("]\n"); 1280 _exit(); 1281 } 1282 1283 // loop on processors for schedulers default values 1284 // initialisation, including WTI and PTI vectors 1285 for ( lpid = 0 ; lpid < cluster[cluster_id].procs ; lpid++ ) 1286 { 1287 // pointer on processor scheduler 1288 psched = (static_scheduler_t*)(sched_vbase + (lpid<<13)); 1289 1290 // initialise the schedulers pointers array 1291 _schedulers[x][y][lpid] = psched; 1292 1293 #if BOOT_DEBUG_SCHED 1294 unsigned int sched_vbase = (unsigned int)_schedulers[x][y][lpid]; 1295 unsigned int sched_ppn; 1296 unsigned int sched_flags; 1297 paddr_t sched_pbase; 1298 1299 page_table_t* ptab = (page_table_t*)(_ptabs_vaddr[0][x][y]); 1300 _v2p_translate( ptab, sched_vbase>>12, &sched_ppn, &sched_flags ); 1301 sched_pbase = ((paddr_t)sched_ppn)<<12; 1302 1303 _puts("\nProc["); 1304 _putd( x ); 1305 _puts(","); 1306 _putd( y ); 1307 _puts(","); 1308 _putd( lpid ); 1309 _puts("] : scheduler vbase = "); 1310 _putx( sched_vbase ); 1311 _puts(" : scheduler pbase = "); 1312 _putl( sched_pbase ); 1313 _puts("\n"); 1314 #endif 1315 // initialise the "tasks" and "current" variables default values 1316 psched->tasks = 0; 1317 psched->current = IDLE_TASK_INDEX; 1318 1319 // default values for HWI / PTI / SWI vectors (valid bit = 0) 1320 unsigned int slot; 1321 for (slot = 0; slot < 32; slot++) 1322 { 1323 psched->hwi_vector[slot] = 0; 1324 psched->pti_vector[slot] = 0; 1325 psched->wti_vector[slot] = 0; 1326 } 1327 1328 // WTI[lpid] <= ISR_WAKUP / PTI[lpid] <= ISR_TICK 1329 psched->wti_vector[lpid] = ISR_WAKUP | 0x80000000; 1330 psched->pti_vector[lpid] = ISR_TICK | 0x80000000; 1331 1332 // initializes the idle_task context in scheduler: 1333 // - the SR slot is 0xFF03 because this task run in kernel mode. 1334 // - it uses the page table of vspace[0] 1335 // - it uses the kernel TTY terminal 1336 // - slots containing addresses (SP, RA, EPC) 1337 // must be initialised by kernel_init() 1338 1339 psched->context[IDLE_TASK_INDEX][CTX_CR_ID] = 0; 1340 psched->context[IDLE_TASK_INDEX][CTX_SR_ID] = 0xFF03; 1341 psched->context[IDLE_TASK_INDEX][CTX_PTPR_ID] = _ptabs_paddr[0][x][y]>>13; 1342 psched->context[IDLE_TASK_INDEX][CTX_PTAB_ID] = _ptabs_vaddr[0][x][y]; 1343 psched->context[IDLE_TASK_INDEX][CTX_TTY_ID] = 0; 1344 psched->context[IDLE_TASK_INDEX][CTX_LTID_ID] = IDLE_TASK_INDEX; 1345 psched->context[IDLE_TASK_INDEX][CTX_VSID_ID] = 0; 1346 psched->context[IDLE_TASK_INDEX][CTX_RUN_ID] = 1; 1347 1348 } // end for processors 1349 1350 // scan HWIs connected to local XCU 1351 // for round-robin allocation to processors 1352 lpid = 0; 1353 for ( irq_id = xcu->irq_offset ; 1354 irq_id < xcu->irq_offset + xcu->irqs ; 1355 irq_id++ ) 1356 { 1357 unsigned int type = irq[irq_id].srctype; 1358 unsigned int srcid = irq[irq_id].srcid; 1359 unsigned int isr = irq[irq_id].isr & 0xFFFF; 1360 unsigned int channel = irq[irq_id].channel << 16; 1361 1362 if ( (type != IRQ_TYPE_HWI) || (srcid > 31) ) 1363 { 1364 _puts("\n[BOOT ERROR] Bad IRQ in XCU of cluster["); 1365 _putd( x ); 1366 _puts(","); 1367 _putd( y ); 1368 _puts("]\n"); 1369 _exit(); 1370 } 1371 1372 _schedulers[x][y][lpid]->hwi_vector[srcid] = isr | channel | 0x80000000; 1373 lpid = (lpid + 1) % cluster[cluster_id].procs; 1374 1375 } // end for irqs 1376 } // end if nprocs > 0 1377 } // end for clusters 1378 1379 // If there is an external PIC component, we scan HWIs connected to PIC 1380 // for Round Robin allocation (as WTI) to processors. 1381 // We allocate one WTI per processor, starting from proc[0,0,0], 1382 // and we increment (cluster_id, lpid) as required. 1383 if ( pic != NULL ) 1384 { 1385 unsigned int cluster_id = 0; // index in clusters array 1386 unsigned int lpid = 0; // processor local index 1387 1388 // scan IRQS defined in PIC 1389 for ( irq_id = pic->irq_offset ; 1390 irq_id < pic->irq_offset + pic->irqs ; 1391 irq_id++ ) 1392 { 1393 // compute next values for (cluster_id,lpid) 1394 // if no more procesor available in current cluster 1395 unsigned int overflow = 0; 1396 while ( (lpid >= cluster[cluster_id].procs) || 1397 (alloc_wti_channel[cluster_id] >= xcu->arg) ) 1398 { 1399 overflow++; 1400 cluster_id = (cluster_id + 1) % (X_SIZE*Y_SIZE); 1401 lpid = 0; 1402 1403 // overflow detection 1404 if ( overflow > (X_SIZE*Y_SIZE*NB_PROCS_MAX*32) ) 1405 { 1406 _puts("\n[BOOT ERROR] Not enough processors for external IRQs\n"); 1407 _exit(); 1408 } 1409 } // end while 1410 1411 unsigned int type = irq[irq_id].srctype; 1412 unsigned int srcid = irq[irq_id].srcid; 1413 unsigned int isr = irq[irq_id].isr & 0xFFFF; 1414 unsigned int channel = irq[irq_id].channel << 16; 1415 1416 if ( (type != IRQ_TYPE_HWI) || (srcid > 31) ) 1417 { 1418 _puts("\n[BOOT ERROR] Bad IRQ in PIC component\n"); 1419 _exit(); 1420 } 1421 1422 // get scheduler[cluster_id] address 1423 unsigned int x = cluster[cluster_id].x; 1424 unsigned int y = cluster[cluster_id].y; 1425 unsigned int cluster_xy = (x<<Y_WIDTH) + y; 1426 psched = _schedulers[x][y][lpid]; 1427 1428 // update WTI vector for scheduler[cluster_id][lpid] 1429 unsigned int index = alloc_wti_channel[cluster_id]; 1430 psched->wti_vector[index] = isr | channel | 0x80000000; 1431 1432 // increment pointers 1433 alloc_wti_channel[cluster_id] = index + 1; 1434 lpid = lpid + 1; 1435 1436 // update IRQ fields in mapping for PIC initialisation 1437 irq[irq_id].dest_id = index; 1438 irq[irq_id].dest_xy = cluster_xy; 1439 1440 } // end for IRQs 1441 } // end if PIC 1442 1443 #if BOOT_DEBUG_SCHED 1444 for ( cluster_id = 0 ; cluster_id < (X_SIZE*Y_SIZE) ; cluster_id++ ) 1445 { 1446 unsigned int x = cluster[cluster_id].x; 1447 unsigned int y = cluster[cluster_id].y; 1448 unsigned int slot; 1449 unsigned int entry; 1450 for ( lpid = 0 ; lpid < cluster[cluster_id].procs ; lpid++ ) 1451 { 1452 psched = _schedulers[x][y][lpid]; 1453 1454 _puts("\n*** IRQS for proc["); 1455 _putd( x ); 1456 _puts(","); 1457 _putd( y ); 1458 _puts(","); 1459 _putd( lpid ); 1460 _puts("]\n"); 1461 for ( slot = 0 ; slot < 32 ; slot++ ) 1462 { 1463 entry = psched->hwi_vector[slot]; 1464 if ( entry & 0x80000000 ) 1465 { 1466 _puts(" - HWI "); 1467 _putd( slot ); 1468 _puts(" / isrtype = "); 1469 _putd( entry & 0xFFFF ); 1470 _puts(" / channel = "); 1471 _putd( (entry >> 16) & 0x7FFF ); 1472 _puts("\n"); 1473 } 1474 } 1475 for ( slot = 0 ; slot < 32 ; slot++ ) 1476 { 1477 entry = psched->wti_vector[slot]; 1478 if ( entry & 0x80000000 ) 1479 { 1480 _puts(" - WTI "); 1481 _putd( slot ); 1482 _puts(" / isrtype = "); 1483 _putd( entry & 0xFFFF ); 1484 _puts(" / channel = "); 1485 _putd( (entry >> 16) & 0x7FFF ); 1486 _puts("\n"); 1487 } 1488 } 1489 for ( slot = 0 ; slot < 32 ; slot++ ) 1490 { 1491 entry = psched->pti_vector[slot]; 1492 if ( entry & 0x80000000 ) 1493 { 1494 _puts(" - PTI "); 1495 _putd( slot ); 1496 _puts(" / isrtype = "); 1497 _putd( entry & 0xFFFF ); 1498 _puts(" / channel = "); 1499 _putd( (entry >> 16) & 0x7FFF ); 1500 _puts("\n"); 1501 } 1502 } 1503 } 1504 } 1505 #endif 1506 1507 /////////////////////////////////////////////////////////////////// 1508 // Step 2 : loop on the vspaces and the tasks to complete 1509 // the schedulers and task contexts initialisation. 1064 } 1065 } 1066 1067 if ( xcu == NULL ) 1068 { 1069 _printf("\n[BOOT ERROR] missing XCU in cluster[%d,%d]\n", x , y ); 1070 _exit(); 1071 } 1072 1073 // scan HWIs connected to local XCU 1074 // for round-robin allocation to local processors 1075 lpid = 0; 1076 for ( irq_id = xcu->irq_offset ; 1077 irq_id < xcu->irq_offset + xcu->irqs ; 1078 irq_id++ ) 1079 { 1080 unsigned int type = irq[irq_id].srctype; 1081 unsigned int srcid = irq[irq_id].srcid; 1082 unsigned int isr = irq[irq_id].isr & 0xFFFF; 1083 unsigned int channel = irq[irq_id].channel << 16; 1084 1085 if ( (type != IRQ_TYPE_HWI) || (srcid > 31) ) 1086 { 1087 _printf("\n[BOOT ERROR] Bad IRQ in cluster[%d,%d]\n", x, y ); 1088 _exit(); 1089 } 1090 1091 _schedulers[x][y][lpid]->hwi_vector[srcid] = isr | channel | 0x80000000; 1092 1093 lpid = (lpid + 1) % nprocs; 1094 } // end for irqs 1095 1096 ////////////////////////////////////////////// 1097 _simple_barrier_wait( &_barrier_all_clusters ); 1098 ////////////////////////////////////////////// 1099 1100 //////////////////////////////////////////////////////////////////////// 1101 // Step 2 : Initialise the tasks context. The context of task placed 1102 // on processor P must be stored in the scheduler of P. 1103 // This require two nested loops: loop on the tasks, and loop 1104 // on the local processors. We complete the scheduler when the 1105 // required placement fit one local processor. 1510 1106 1511 1107 for (vspace_id = 0; vspace_id < header->vspaces; vspace_id++) … … 1513 1109 // We must set the PTPR depending on the vspace, because the start_vector 1514 1110 // and the stack address are defined in virtual space. 1515 _set_mmu_ptpr( (unsigned int)(_ptabs_paddr[vspace_id][ 0][0] >> 13) );1111 _set_mmu_ptpr( (unsigned int)(_ptabs_paddr[vspace_id][x][y] >> 13) ); 1516 1112 1517 1113 // loop on the tasks in vspace (task_id is the global index in mapping) … … 1520 1116 task_id++) 1521 1117 { 1522 // compute the cluster coordinates & local processor index 1523 unsigned int x = cluster[task[task_id].clusterid].x; 1524 unsigned int y = cluster[task[task_id].clusterid].y; 1525 unsigned int cluster_xy = (x<<Y_WIDTH) + y; 1526 unsigned int lpid = task[task_id].proclocid; 1527 1528 #if BOOT_DEBUG_SCHED 1529 _puts("\n[BOOT DEBUG] Initialise context for task "); 1530 _puts( task[task_id].name ); 1531 _puts(" in vspace "); 1532 _puts( vspace[vspace_id].name ); 1533 _puts("\n"); 1534 #endif 1535 // compute gpid (global processor index) and scheduler base address 1536 unsigned int gpid = (cluster_xy << P_WIDTH) + lpid; 1537 psched = _schedulers[x][y][lpid]; 1118 // get the required task placement coordinates [x,y,p] 1119 unsigned int req_x = cluster[task[task_id].clusterid].x; 1120 unsigned int req_y = cluster[task[task_id].clusterid].y; 1121 unsigned int req_p = task[task_id].proclocid; 1538 1122 1539 1123 // ctx_sr : value required before an eret instruction … … 1541 1125 1542 1126 // ctx_ptpr : page table physical base address (shifted by 13 bit) 1543 unsigned int ctx_ptpr = ( unsigned int)(_ptabs_paddr[vspace_id][x][y] >> 13);1127 unsigned int ctx_ptpr = (_ptabs_paddr[vspace_id][req_x][req_y] >> 13); 1544 1128 1545 1129 // ctx_ptab : page_table virtual base address 1546 unsigned int ctx_ptab = _ptabs_vaddr[vspace_id][ x][y];1130 unsigned int ctx_ptab = _ptabs_vaddr[vspace_id][req_x][req_y]; 1547 1131 1548 1132 // ctx_epc : Get the virtual address of the memory location containing … … 1556 1140 unsigned int ctx_sp = vobj[vobj_id].vbase + vobj[vobj_id].length; 1557 1141 1558 // get local task index in scheduler1559 unsigned int ltid = psched->tasks;1560 1561 1142 // get vspace thread index 1562 1143 unsigned int thread_id = task[task_id].trdid; 1563 1144 1564 if (ltid >= IDLE_TASK_INDEX) 1145 // loop on the local processors 1146 for ( lpid = 0 ; lpid < nprocs ; lpid++ ) 1565 1147 { 1566 _puts("\n[BOOT ERROR] in boot_schedulers_init() : "); 1567 _putd( ltid ); 1568 _puts(" tasks allocated to processor "); 1569 _putd( gpid ); 1570 _puts(" / max is "); 1571 _putd( IDLE_TASK_INDEX ); 1572 _puts("\n"); 1148 if ( (x == req_x) && (y == req_y) && (req_p == lpid) ) // fit 1149 { 1150 // pointer on selected scheduler 1151 psched = _schedulers[x][y][lpid]; 1152 1153 // get local task index in scheduler 1154 unsigned int ltid = psched->tasks; 1155 1156 // update the "tasks" and "current" fields in scheduler: 1157 psched->tasks = ltid + 1; 1158 psched->current = 0; 1159 1160 // initializes the task context 1161 psched->context[ltid][CTX_CR_ID] = 0; 1162 psched->context[ltid][CTX_SR_ID] = ctx_sr; 1163 psched->context[ltid][CTX_SP_ID] = ctx_sp; 1164 psched->context[ltid][CTX_EPC_ID] = ctx_epc; 1165 psched->context[ltid][CTX_PTPR_ID] = ctx_ptpr; 1166 psched->context[ltid][CTX_PTAB_ID] = ctx_ptab; 1167 psched->context[ltid][CTX_LTID_ID] = ltid; 1168 psched->context[ltid][CTX_GTID_ID] = task_id; 1169 psched->context[ltid][CTX_TRDID_ID] = thread_id; 1170 psched->context[ltid][CTX_VSID_ID] = vspace_id; 1171 psched->context[ltid][CTX_RUN_ID] = 1; 1172 1173 psched->context[ltid][CTX_TTY_ID] = 0xFFFFFFFF; 1174 psched->context[ltid][CTX_CMA_FB_ID] = 0xFFFFFFFF; 1175 psched->context[ltid][CTX_CMA_RX_ID] = 0xFFFFFFFF; 1176 psched->context[ltid][CTX_CMA_TX_ID] = 0xFFFFFFFF; 1177 psched->context[ltid][CTX_NIC_RX_ID] = 0xFFFFFFFF; 1178 psched->context[ltid][CTX_NIC_TX_ID] = 0xFFFFFFFF; 1179 psched->context[ltid][CTX_TIM_ID] = 0xFFFFFFFF; 1180 psched->context[ltid][CTX_HBA_ID] = 0xFFFFFFFF; 1181 1182 #if BOOT_DEBUG_SCHED 1183 _printf("\nTask %s in vspace %s allocated to P[%d,%d,%d]\n" 1184 " - ctx[LTID] = %d\n" 1185 " - ctx[SR] = %x\n" 1186 " - ctx[SP] = %x\n" 1187 " - ctx[EPC] = %x\n" 1188 " - ctx[PTPR] = %x\n" 1189 " - ctx[PTAB] = %x\n" 1190 " - ctx[VSID] = %d\n" 1191 " - ctx[TRDID] = %d\n", 1192 task[task_id].name, 1193 vspace[vspace_id].name, 1194 x, y, lpid, 1195 psched->context[ltid][CTX_LTID_ID], 1196 psched->context[ltid][CTX_SR_ID], 1197 psched->context[ltid][CTX_SP_ID], 1198 psched->context[ltid][CTX_EPC_ID], 1199 psched->context[ltid][CTX_PTPR_ID], 1200 psched->context[ltid][CTX_PTAB_ID], 1201 psched->context[ltid][CTX_VSID_ID], 1202 psched->context[ltid][CTX_TRDID_ID] ); 1203 #endif 1204 } // end if FIT 1205 } // end for loop on local procs 1206 } // end loop on tasks 1207 } // end loop on vspaces 1208 } // end boot_scheduler_init() 1209 1210 1211 ///////////////////////////////////////////////////////////////////////////// 1212 // This function loops on all processors in all clusters to display 1213 // the interrupt vectors for each processor. 1214 ///////////////////////////////////////////////////////////////////////////// 1215 void boot_sched_irq_display() 1216 { 1217 unsigned int cx; 1218 unsigned int cy; 1219 unsigned int lpid; 1220 unsigned int slot; 1221 unsigned int entry; 1222 1223 mapping_header_t* header = (mapping_header_t *)SEG_BOOT_MAPPING_BASE; 1224 mapping_cluster_t* cluster = _get_cluster_base(header); 1225 1226 static_scheduler_t* psched; 1227 1228 for ( cx = 0 ; cx < X_SIZE ; cx++ ) 1229 { 1230 for ( cy = 0 ; cy < Y_SIZE ; cy++ ) 1231 { 1232 unsigned int cluster_id = (cx * Y_SIZE) + cy; 1233 unsigned int nprocs = cluster[cluster_id].procs; 1234 1235 for ( lpid = 0 ; lpid < nprocs ; lpid++ ) 1236 { 1237 psched = _schedulers[cx][cy][lpid]; 1238 1239 _printf("\n[BOOT] scheduler for proc[%d,%d,%d] : ntasks = %d\n", 1240 cx , cy , lpid , psched->tasks ); 1241 1242 for ( slot = 0 ; slot < 32 ; slot++ ) 1243 { 1244 entry = psched->hwi_vector[slot]; 1245 if ( entry & 0x80000000 ) 1246 _printf(" - HWI %d / isrtype = %d / channel = %d\n", 1247 slot , (entry & 0xFFFF) , ((entry >> 16) & 0x7FFF) ); 1248 } 1249 for ( slot = 0 ; slot < 32 ; slot++ ) 1250 { 1251 entry = psched->wti_vector[slot]; 1252 if ( entry & 0x80000000 ) 1253 _printf(" - WTI %d / isrtype = %d / channel = %d\n", 1254 slot , (entry & 0xFFFF) , ((entry >> 16) & 0x7FFF) ); 1255 } 1256 for ( slot = 0 ; slot < 32 ; slot++ ) 1257 { 1258 entry = psched->pti_vector[slot]; 1259 if ( entry & 0x80000000 ) 1260 _printf(" - PTI %d / isrtype = %d / channel = %d\n", 1261 slot , (entry & 0xFFFF) , ((entry >> 16) & 0x7FFF) ); 1262 } 1263 } 1264 } 1265 } 1266 } // end boot_sched_display() 1267 1268 1269 ///////////////////////////////////////////////////////////////////////////// 1270 // This function complete the schedulers initialisation when the platform 1271 // contains a PIC component in the IO cluster. 1272 // It is executed by P[0][0][0] only. 1273 // It scan HWIs connected to PIC for Round Robin allocation to processors, 1274 // as WTI. It allocates one WTI per processor, starting from P[0,0,0], 1275 // and increments (cluster_id, lpid) as required. 1276 ///////////////////////////////////////////////////////////////////////////// 1277 void boot_pic_wti_init() 1278 { 1279 mapping_header_t* header = (mapping_header_t *)SEG_BOOT_MAPPING_BASE; 1280 mapping_cluster_t* cluster = _get_cluster_base(header); 1281 mapping_periph_t* periph = _get_periph_base(header); 1282 mapping_irq_t* irq = _get_irq_base(header); 1283 1284 unsigned int periph_id; // peripheral index in mapping_info 1285 unsigned int irq_id; // irq index in mapping_info 1286 1287 // get cluster_io index in mapping 1288 unsigned int x_io = header->x_io; 1289 unsigned int y_io = header->y_io; 1290 unsigned int cluster_io = (x_io * Y_SIZE) + y_io; 1291 1292 // scan peripherals in cluster_io to find PIC 1293 mapping_periph_t* pic = NULL; 1294 1295 for ( periph_id = cluster[cluster_io].periph_offset ; 1296 periph_id < cluster[cluster_io].periph_offset + cluster[cluster_io].periphs; 1297 periph_id++ ) 1298 { 1299 if ( periph[periph_id].type == PERIPH_TYPE_PIC ) 1300 { 1301 pic = &periph[periph_id]; 1302 break; 1303 } 1304 } 1305 1306 if ( pic == NULL ) return; 1307 1308 // initialize WTI channel allocators in all clusters 1309 unsigned int x; 1310 unsigned int y; 1311 for ( x = 0 ; x < X_SIZE ; x++ ) 1312 { 1313 for ( y = 0 ; y < Y_SIZE ; y++ ) 1314 { 1315 _wti_channel_alloc[x][y] = NB_PROCS_MAX; 1316 } 1317 } 1318 1319 // scan IRQS defined in PIC 1320 unsigned int cluster_id = 0; 1321 unsigned int lpid = 0; 1322 unsigned int cx = cluster[cluster_id].x; 1323 unsigned int cy = cluster[cluster_id].y; 1324 1325 for ( irq_id = pic->irq_offset ; 1326 irq_id < pic->irq_offset + pic->irqs ; 1327 irq_id++ ) 1328 { 1329 // compute next values for cluster_id, lpid, cx, cy 1330 // if no more WTI allocatable in current cluster 1331 unsigned int overflow = 0; 1332 1333 while ( (lpid >= cluster[cluster_id].procs) || 1334 (_wti_channel_alloc[cx][cy] >= 16) ) 1335 { 1336 cluster_id = (cluster_id + 1) % (X_SIZE*Y_SIZE); 1337 cx = cluster[cluster_id].x; 1338 cy = cluster[cluster_id].y; 1339 lpid = 0; 1340 1341 overflow++; 1342 1343 if ( overflow > 1024 ) 1344 { 1345 _printf("\n[BOOT ERROR] Not enough processors for external IRQs\n"); 1573 1346 _exit(); 1574 1347 } 1575 1576 // update the "tasks" and "current" fields in scheduler: 1577 // the first task to execute is task 0 as soon as there is at least 1578 // one task allocated to processor. 1579 psched->tasks = ltid + 1; 1580 psched->current = 0; 1581 1582 // initializes the task context 1583 psched->context[ltid][CTX_CR_ID] = 0; 1584 psched->context[ltid][CTX_SR_ID] = ctx_sr; 1585 psched->context[ltid][CTX_SP_ID] = ctx_sp; 1586 psched->context[ltid][CTX_EPC_ID] = ctx_epc; 1587 psched->context[ltid][CTX_PTPR_ID] = ctx_ptpr; 1588 psched->context[ltid][CTX_PTAB_ID] = ctx_ptab; 1589 psched->context[ltid][CTX_LTID_ID] = ltid; 1590 psched->context[ltid][CTX_GTID_ID] = task_id; 1591 psched->context[ltid][CTX_TRDID_ID] = thread_id; 1592 psched->context[ltid][CTX_VSID_ID] = vspace_id; 1593 psched->context[ltid][CTX_RUN_ID] = 1; 1594 1595 psched->context[ltid][CTX_TTY_ID] = 0xFFFFFFFF; 1596 psched->context[ltid][CTX_CMA_FB_ID] = 0xFFFFFFFF; 1597 psched->context[ltid][CTX_CMA_RX_ID] = 0xFFFFFFFF; 1598 psched->context[ltid][CTX_CMA_TX_ID] = 0xFFFFFFFF; 1599 psched->context[ltid][CTX_NIC_RX_ID] = 0xFFFFFFFF; 1600 psched->context[ltid][CTX_NIC_TX_ID] = 0xFFFFFFFF; 1601 psched->context[ltid][CTX_TIM_ID] = 0xFFFFFFFF; 1602 psched->context[ltid][CTX_HBA_ID] = 0xFFFFFFFF; 1348 } 1349 // allocate a WTI to processor defined by (cluster_id,lpid) 1350 unsigned int type = irq[irq_id].srctype; 1351 unsigned int srcid = irq[irq_id].srcid; 1352 unsigned int isr = irq[irq_id].isr & 0xFFFF; 1353 unsigned int channel = irq[irq_id].channel << 16; 1354 1355 if ( (type != IRQ_TYPE_HWI) || (srcid > 31) ) 1356 { 1357 _printf("\n[BOOT ERROR] in boot_pic_wti_init() Bad IRQ type\n"); 1358 _exit(); 1359 } 1360 1361 // get scheduler address for selected processor 1362 static_scheduler_t* psched = _schedulers[cx][cy][lpid]; 1363 1364 // update WTI vector for selected processor 1365 unsigned int index = _wti_channel_alloc[cx][cy]; 1366 psched->wti_vector[index] = isr | channel | 0x80000000; 1367 1368 // update IRQ fields in mapping for PIC initialisation 1369 irq[irq_id].dest_id = index; 1370 irq[irq_id].dest_xy = (cx << Y_WIDTH) + cy; 1371 1372 // update pointers 1373 _wti_channel_alloc[cx][cy] = index + 1; 1374 lpid = lpid + 1; 1375 1376 } // end for IRQs 1603 1377 1604 1378 #if BOOT_DEBUG_SCHED 1605 _puts("\nTask "); 1606 _putd( task_id ); 1607 _puts(" allocated to processor["); 1608 _putd( x ); 1609 _puts(","); 1610 _putd( y ); 1611 _puts(","); 1612 _putd( lpid ); 1613 _puts("]\n - ctx[LTID] = "); 1614 _putd( psched->context[ltid][CTX_LTID_ID] ); 1615 _puts("\n - ctx[SR] = "); 1616 _putx( psched->context[ltid][CTX_SR_ID] ); 1617 _puts("\n - ctx[SP] = "); 1618 _putx( psched->context[ltid][CTX_SP_ID] ); 1619 _puts("\n - ctx[EPC] = "); 1620 _putx( psched->context[ltid][CTX_EPC_ID] ); 1621 _puts("\n - ctx[PTPR] = "); 1622 _putx( psched->context[ltid][CTX_PTPR_ID] ); 1623 _puts("\n - ctx[PTAB] = "); 1624 _putx( psched->context[ltid][CTX_PTAB_ID] ); 1625 _puts("\n - ctx[GTID] = "); 1626 _putx( psched->context[ltid][CTX_GTID_ID] ); 1627 _puts("\n - ctx[VSID] = "); 1628 _putx( psched->context[ltid][CTX_VSID_ID] ); 1629 _puts("\n - ctx[TRDID] = "); 1630 _putx( psched->context[ltid][CTX_TRDID_ID] ); 1631 _puts("\n"); 1632 #endif 1633 1634 } // end loop on tasks 1635 } // end loop on vspaces 1636 } // end boot_schedulers_init() 1637 1379 boot_sched_irq_display(); 1380 #endif 1381 1382 } // end boot_pic_wti_init() 1383 1638 1384 ////////////////////////////////////////////////////////////////////////////////// 1639 1385 // This function loads the map.bin file from block device. … … 1650 1396 if ( fd_id == -1 ) 1651 1397 { 1652 _p uts("\n[BOOT ERROR] : map.bin file not found \n");1398 _printf("\n[BOOT ERROR] : map.bin file not found \n"); 1653 1399 _exit(); 1654 1400 } 1655 1401 1656 1402 #if BOOT_DEBUG_MAPPING 1657 _puts("\n[BOOT] map.bin file successfully open at cycle "); 1658 _putd(_get_proctime()); 1659 _puts("\n"); 1403 _printf("\n[BOOT] map.bin file successfully open at cycle %d\n", _get_proctime() ); 1660 1404 #endif 1661 1405 … … 1665 1409 if ( size > SEG_BOOT_MAPPING_SIZE ) 1666 1410 { 1667 _p uts("\n[BOOT ERROR] : allocated segment too small for map.bin file\n");1411 _printf("\n[BOOT ERROR] : allocated segment too small for map.bin file\n"); 1668 1412 _exit(); 1669 1413 } 1670 1414 1671 1415 #if BOOT_DEBUG_MAPPING 1672 _puts("\n[BOOT] map.bin buffer pbase = "); 1673 _putx( SEG_BOOT_MAPPING_BASE ); 1674 _puts(" / buffer size = "); 1675 _putx( SEG_BOOT_MAPPING_SIZE ); 1676 _puts(" / file size = "); 1677 _putx( size ); 1678 _puts("\n"); 1416 _printf("\n[BOOT] map.bin buffer pbase = %x / buffer size = %x / file_size = %x\n", 1417 SEG_BOOT_MAPPING_BASE , SEG_BOOT_MAPPING_SIZE , size ); 1679 1418 #endif 1680 1419 … … 1691 1430 if ( ok == -1 ) 1692 1431 { 1693 _p uts("\n[BOOT ERROR] : unable to load map.bin file \n");1432 _printf("\n[BOOT ERROR] : unable to load map.bin file \n"); 1694 1433 _exit(); 1695 1434 } 1696 1435 1697 1436 #if BOOT_DEBUG_MAPPING 1698 _puts("\n[BOOT] map.bin file successfully loaded at cycle "); 1699 _putd(_get_proctime()); 1700 _puts("\n"); 1437 _printf("\n[BOOT] map.bin file successfully loaded at cycle %d\n", _get_proctime() ); 1701 1438 #endif 1702 1439 … … 1710 1447 1711 1448 #if BOOT_DEBUG_MAPPING 1712 unsigned int word;1713 1449 unsigned int line; 1714 1450 unsigned int* pointer = (unsigned int*)SEG_BOOT_MAPPING_BASE; 1715 _p uts("\n[BOOT] First block of mapping\n");1451 _printf("\n[BOOT] First block of mapping\n"); 1716 1452 for ( line = 0 ; line < 8 ; line++ ) 1717 1453 { 1718 for ( word = 0 ; word < 8 ; word++ ) 1719 { 1720 _puts(" | "); 1721 _putx( *(pointer + word) ); 1722 } 1723 _puts(" |\n"); 1454 _printf(" | %x | %x | %x | %x | %x | %x | %x | %x |\n", 1455 *(pointer + 0), 1456 *(pointer + 1), 1457 *(pointer + 2), 1458 *(pointer + 3), 1459 *(pointer + 4), 1460 *(pointer + 5), 1461 *(pointer + 6), 1462 *(pointer + 7) ); 1463 1724 1464 pointer = pointer + 8; 1725 1465 } 1726 1466 #endif 1727 _puts("\n[BOOT ERROR] Illegal mapping signature: "); 1728 _putx(header->signature); 1729 _puts("\n"); 1467 _printf("\n[BOOT ERROR] Illegal mapping signature: %x\n", header->signature ); 1730 1468 _exit(); 1731 1469 } 1732 1470 1733 1471 #if BOOT_DEBUG_MAPPING 1734 _puts("\n[BOOT] map.bin file checked at cycle "); 1735 _putd(_get_proctime()); 1736 _puts("\n"); 1472 _printf("\n[BOOT] map.bin file checked at cycle %d\n", _get_proctime() ); 1737 1473 #endif 1738 1474 … … 1770 1506 1771 1507 #if BOOT_DEBUG_ELF 1772 _puts("\n[BOOT DEBUG] Start searching file "); 1773 _puts( pathname ); 1774 _puts(" at cycle "); 1775 _putd( _get_proctime() ); 1776 _puts("\n"); 1508 _printf("\n[BOOT] Start searching file %s at cycle %d\n", 1509 pathname, _get_proctime() ); 1777 1510 #endif 1778 1511 … … 1783 1516 if ( fd_id < 0 ) 1784 1517 { 1785 _puts("\n[BOOT ERROR] load_one_elf_file() : "); 1786 _puts( pathname ); 1787 _puts(" not found\n"); 1518 _printf("\n[BOOT ERROR] load_one_elf_file() : %s not found\n", pathname ); 1788 1519 _exit(); 1789 1520 } … … 1792 1523 if ( fat.fd[fd_id].file_size > GIET_ELF_BUFFER_SIZE ) 1793 1524 { 1794 _puts("\n[BOOT ERROR] in load_one_elf_file() : "); 1795 _puts( pathname ); 1796 _puts(" size = "); 1797 _putx( fat.fd[fd_id].file_size ); 1798 _puts("\n exceeds the GIET_ELF_BUFFERSIZE = "); 1799 _putx( GIET_ELF_BUFFER_SIZE ); 1800 _puts("\n"); 1525 _printf("\n[BOOT ERROR] in load_one_elf_file() : %s / size = %x " 1526 "larger than GIET_ELF_BUFFER_SIZE = %x\n", 1527 pathname , fat.fd[fd_id].file_size , GIET_ELF_BUFFER_SIZE ); 1801 1528 _exit(); 1802 1529 } … … 1814 1541 0 ) != nsectors ) 1815 1542 { 1816 _puts("\n[BOOT ERROR] load_one_elf_file() : unexpected EOF for file "); 1817 _puts( pathname ); 1818 _puts("\n"); 1543 _printf("\n[BOOT ERROR] load_one_elf_file() : unexpected EOF for file %s\n", 1544 pathname ); 1819 1545 _exit(); 1820 1546 } … … 1828 1554 (elf_header_ptr->e_ident[EI_MAG3] != ELFMAG3) ) 1829 1555 { 1830 _puts("\n[BOOT ERROR] load_elf() : file "); 1831 _puts( pathname ); 1832 _puts(" does not use ELF format\n"); 1556 _printf("\n[BOOT ERROR] load_elf() : file %s does not use ELF format\n", 1557 pathname ); 1833 1558 _exit(); 1834 1559 } … … 1838 1563 if( pht_index == 0 ) 1839 1564 { 1840 _puts("\n[BOOT ERROR] load_one_elf_file() : file "); 1841 _puts( pathname ); 1842 _puts(" does not contain loadable segment\n"); 1565 _printf("\n[BOOT ERROR] load_one_elf_file() : file %s " 1566 "does not contain loadable segment\n", pathname ); 1843 1567 _exit(); 1844 1568 } … … 1847 1571 // get number of segments 1848 1572 unsigned int nsegments = elf_header_ptr->e_phnum; 1849 1850 _puts("\n[BOOT] File ");1851 _puts( pathname );1852 _puts(" loaded at cycle ");1853 _putd( _get_proctime() );1854 _puts("\n");1855 1573 1856 1574 // Loop on loadable segments in the .elf file … … 1866 1584 1867 1585 #if BOOT_DEBUG_ELF 1868 _puts(" - segment "); 1869 _putd( seg_id ); 1870 _puts(" / vaddr = "); 1871 _putx( seg_vaddr ); 1872 _puts(" / file_size = "); 1873 _putx( seg_filesz ); 1874 _puts("\n"); 1586 _printf("\n[BOOT] Segment %d : vaddr = %x / size = %x\n", 1587 seg_id , seg_vaddr , seg_filesz ); 1875 1588 #endif 1876 1589 1877 1590 if( seg_memsz < seg_filesz ) 1878 1591 { 1879 _puts("\n[BOOT ERROR] load_one_elf_file() : segment at vaddr = "); 1880 _putx( seg_vaddr ); 1881 _puts(" in file "); 1882 _puts( pathname ); 1883 _puts(" has memsz < filesz \n"); 1592 _printf("\n[BOOT ERROR] load_one_elf_file() : segment at vaddr = %x" 1593 " in file %s has memsize < filesize \n", seg_vaddr, pathname ); 1884 1594 _exit(); 1885 1595 } … … 1889 1599 { 1890 1600 unsigned int i; 1891 for( i = seg_filesz ; i < seg_memsz ; i++ ) boot_elf_buffer[i+seg_offset] = 0; 1601 for( i = seg_filesz ; i < seg_memsz ; i++ ) 1602 boot_elf_buffer[i+seg_offset] = 0; 1892 1603 } 1893 1604 … … 1922 1633 1923 1634 #if BOOT_DEBUG_ELF 1924 _puts(" loaded into vseg "); 1925 _puts( vseg[vseg_id].name ); 1926 _puts(" at paddr = "); 1927 _putl( seg_paddr ); 1928 _puts(" (buffer size = "); 1929 _putx( seg_size ); 1930 _puts(")\n"); 1635 _printf(" loaded into vseg %s at paddr = %l / buffer size = %x\n", 1636 vseg[vseg_id].name , seg_paddr , seg_size ); 1931 1637 #endif 1932 1638 // check vseg size 1933 1639 if ( seg_size < seg_filesz ) 1934 1640 { 1935 _puts("\n[BOOT ERROR] in load_one_elf_file()\n"); 1936 _puts("vseg "); 1937 _puts( vseg[vseg_id].name ); 1938 _puts(" is to small for loadable segment "); 1939 _putx( seg_vaddr ); 1940 _puts(" in file "); 1941 _puts( pathname ); 1942 _puts(" \n"); 1641 _printf("\n[BOOT ERROR] in load_one_elf_file() : vseg %s " 1642 "is to small for loadable segment %x in file %s\n", 1643 vseg[vseg_id].name , seg_vaddr , pathname ); 1943 1644 _exit(); 1944 1645 } … … 1966 1667 if ( found == 0 ) 1967 1668 { 1968 _puts("\n[BOOT ERROR] in load_one_elf_file()\n"); 1969 _puts("vseg for loadable segment "); 1970 _putx( seg_vaddr ); 1971 _puts(" in file "); 1972 _puts( pathname ); 1973 _puts(" not found: \n"); 1974 _puts(" check consistency between the .py and .ld files...\n"); 1669 _printf("\n[BOOT ERROR] in load_one_elf_file() : vseg for loadable " 1670 "segment %x in file %s not found " 1671 "check consistency between the .py and .ld files\n", 1672 seg_vaddr, pathname ); 1975 1673 _exit(); 1976 1674 } … … 1980 1678 // close .elf file 1981 1679 _fat_close( fd_id ); 1680 1681 _printf("\n[BOOT] File %s loaded at cycle %d\n", 1682 pathname , _get_proctime() ); 1982 1683 1983 1684 } // end load_one_elf_file() … … 2018 1719 if (found == 0) 2019 1720 { 2020 _p uts("[BOOT ERROR] boot_elf_load() : kernel.elf file not found\n");1721 _printf("\n[BOOT ERROR] boot_elf_load() : kernel.elf file not found\n"); 2021 1722 _exit(); 2022 1723 } … … 2047 1748 if (found == 0) 2048 1749 { 2049 _puts("[BOOT ERROR] boot_elf_load() : .elf file not found for vspace "); 2050 _puts( vspace[vspace_id].name ); 2051 _puts("\n"); 1750 _printf("\n[BOOT ERROR] boot_elf_load() : " 1751 ".elf file not found for vspace %s\n", vspace[vspace_id].name ); 2052 1752 _exit(); 2053 1753 } … … 2090 1790 2091 1791 #if BOOT_DEBUG_PERI 2092 _puts("\n[BOOT DEBUG] Peripherals initialisation in cluster["); 2093 _putd( x ); 2094 _puts(","); 2095 _putd( y ); 2096 _puts("]\n"); 1792 _printf("\n[BOOT] Peripherals initialisation in cluster[%d,%d]\n", x , y ); 2097 1793 #endif 2098 1794 … … 2171 1867 2172 1868 #if BOOT_DEBUG_PERI 2173 unsigned int address = _pic_get_register( channel_id, IOPIC_ADDRESS ); 2174 unsigned int extend = _pic_get_register( channel_id, IOPIC_EXTEND ); 2175 _puts(" hwi_index = "); 2176 _putd( hwi_id ); 2177 _puts(" / wti_index = "); 2178 _putd( wti_id ); 2179 _puts(" / vaddr = "); 2180 _putx( vaddr ); 2181 _puts(" in cluster["); 2182 _putd( cluster_xy >> Y_WIDTH ); 2183 _puts(","); 2184 _putd( cluster_xy & ((1<<Y_WIDTH)-1) ); 2185 _puts("] / checked_xcu_paddr = "); 2186 _putl( (paddr_t)address + (((paddr_t)extend)<<32) ); 2187 _puts("\n"); 1869 _printf("[BOOT] PIC : hwi_index = %d => wti_index = %d for XCU[%d,%d]\n", 1870 hwi_id , wti_id , cluster_xy >> Y_WIDTH , cluster_xy & ((1<<Y_WIDTH)-1) ); 2188 1871 #endif 2189 1872 } … … 2194 1877 2195 1878 #if BOOT_DEBUG_PERI 2196 _puts("\n[BOOT DEBUG] Coprocessors initialisation in cluster["); 2197 _putd( x ); 2198 _puts(","); 2199 _putd( y ); 2200 _puts("]\n"); 1879 _printf("\n[BOOT] Coprocessors initialisation in cluster[%d,%d]\n", x , y ); 2201 1880 #endif 2202 1881 … … 2206 1885 cluster[cluster_id].coprocs; coproc_id++ ) 2207 1886 { 2208 2209 #if BOOT_DEBUG_PERI2210 _puts("- coprocessor name : ");2211 _puts(coproc[coproc_id].name);2212 _puts(" / nb ports = ");2213 _putd((unsigned int) coproc[coproc_id].ports);2214 _puts("\n");2215 #endif2216 1887 // loop on the coprocessor ports 2217 1888 for ( cp_port_id = coproc[coproc_id].port_offset; … … 2241 1912 cp_port[cp_port_id].direction, 2242 1913 pbase ); 2243 #if BOOT_DEBUG_PERI 2244 _puts(" port direction: "); 2245 _putd( (unsigned int)cp_port[cp_port_id].direction ); 2246 _puts(" / mwmr_channel_pbase = "); 2247 _putl( pbase ); 2248 _puts(" / name = "); 2249 _puts(vobj[vobj_id].name); 2250 _puts("\n"); 2251 #endif 1914 2252 1915 } // end for cp_ports 2253 1916 } // end for coprocs … … 2255 1918 } // end boot_peripherals_init() 2256 1919 2257 ///////////////////////////////////////////////////////////////////////// 2258 // This function i nitialises the physical memory allocators in each2259 // cluster containing a RAM pseg.2260 // it is handled by the processor[x][y][0]2261 ///////////////////////////////////////////////////////////////////////// 2262 void boot_pmem_init()1920 /////////////////////////////////////////////////////////////////////////////////////// 1921 // This function is executed in parallel by all processors[x][y][0]. 1922 // It initialises the physical memory allocator in each cluster containing a RAM pseg. 1923 /////////////////////////////////////////////////////////////////////////////////////// 1924 void boot_pmem_init( unsigned int cx, 1925 unsigned int cy ) 2263 1926 { 2264 1927 mapping_header_t* header = (mapping_header_t *)SEG_BOOT_MAPPING_BASE; … … 2266 1929 mapping_pseg_t* pseg = _get_pseg_base(header); 2267 1930 2268 unsigned int cluster_id;2269 1931 unsigned int pseg_id; 2270 1932 unsigned int procid = _get_procid(); 2271 unsigned int x_cluster = (procid >> (Y_WIDTH + P_WIDTH)) & ((1<<X_WIDTH)-1);2272 unsigned int y_cluster = (procid >> P_WIDTH) & ((1<<Y_WIDTH)-1);2273 1933 unsigned int lpid = procid & ((1<<P_WIDTH)-1); 2274 if(lpid) 2275 { 2276 _puts("[BOOT ERROR] boot_pmem_init() : error local processor id\n"); 1934 1935 if( lpid ) 1936 { 1937 _printf("\n[BOOT ERROR] boot_pmem_init() : " 1938 "P[%d][%d][%d] should not execute it\n", cx, cy, lpid ); 2277 1939 _exit(); 2278 } // scan all clusters 2279 2280 cluster_id = x_cluster * Y_SIZE + y_cluster; 2281 // scan the psegs in cluster to find first pseg of type RAM 2282 unsigned int pseg_min = cluster[cluster_id].pseg_offset; 2283 unsigned int pseg_max = pseg_min + cluster[cluster_id].psegs; 1940 } 1941 1942 // scan the psegs in local cluster to find pseg of type RAM 1943 unsigned int found = 0; 1944 unsigned int cluster_id = cx * Y_SIZE + cy; 1945 unsigned int pseg_min = cluster[cluster_id].pseg_offset; 1946 unsigned int pseg_max = pseg_min + cluster[cluster_id].psegs; 2284 1947 for ( pseg_id = pseg_min ; pseg_id < pseg_max ; pseg_id++ ) 2285 1948 { 2286 1949 if ( pseg[pseg_id].type == PSEG_TYPE_RAM ) 2287 1950 { 2288 unsigned int x = cluster[cluster_id].x;2289 unsigned int y = cluster[cluster_id].y;2290 if(x != x_cluster || y != y_cluster)2291 {2292 _puts("[BOOT ERROR] boot_pmem_init() : error cluster id \n");2293 _exit();2294 }2295 1951 unsigned int base = (unsigned int)pseg[pseg_id].base; 2296 1952 unsigned int size = (unsigned int)pseg[pseg_id].length; 2297 _pmem_alloc_init( x, y, base, size ); 1953 _pmem_alloc_init( cx, cy, base, size ); 1954 found = 1; 2298 1955 2299 1956 #if BOOT_DEBUG_PT 2300 _get_lock(&lock_tty); 2301 _puts("\n[BOOT DEBUG] pmem allocator initialised in cluster["); 2302 _putd( x ); 2303 _puts(","); 2304 _putd( y ); 2305 _puts("] base = "); 2306 _putx( base ); 2307 _puts(" / size = "); 2308 _putx( size ); 2309 _puts("\n"); 2310 _release_lock(&lock_tty); 1957 _printf("\n[BOOT] pmem allocator initialised in cluster[%d][%d]" 1958 " : base = %x / size = %x\n", cx , cy , base , size ); 2311 1959 #endif 2312 1960 break; 2313 1961 } 2314 1962 } 1963 1964 if ( found == 0 ) 1965 { 1966 _printf("\n[BOOT ERROR] boot_pmem_init() : no RAM in cluster[%d][%d]\n", 1967 cx , cy ); 1968 _exit(); 1969 } 2315 1970 } // end boot_pmem_init() 2316 1971 2317 1972 ///////////////////////////////////////////////////////////////////////// 2318 1973 // This function is the entry point of the boot code for all processors. 2319 // Most of this code is executed by Processor 0 only.2320 1974 ///////////////////////////////////////////////////////////////////////// 2321 1975 void boot_init() … … 2323 1977 mapping_header_t* header = (mapping_header_t *)SEG_BOOT_MAPPING_BASE; 2324 1978 mapping_cluster_t* cluster = _get_cluster_base(header); 1979 2325 1980 unsigned int gpid = _get_procid(); 2326 unsigned int clusterid, p; 2327 2328 if ( gpid == 0 ) // only Processor 0 does it 2329 { 2330 _puts("\n[BOOT] boot_init start at cycle "); 2331 _putd(_get_proctime()); 2332 _puts("\n"); 1981 unsigned int cx = gpid >> (Y_WIDTH + P_WIDTH); 1982 unsigned int cy = (gpid >> P_WIDTH) & ((1<<Y_WIDTH)-1); 1983 unsigned int lpid = gpid & ((1 << P_WIDTH) -1); 1984 unsigned int cluster_id = (cx * Y_SIZE) + cy; 1985 1986 // Phase ONE : only P[0][0][0] execute it 1987 if ( gpid == 0 ) 1988 { 1989 unsigned int cid; // index for loops 1990 1991 // initialises the TTY0 spin lock 1992 _spin_lock_init( &_tty0_spin_lock ); 1993 1994 _printf("\n[BOOT] P[0,0,0] starts at cycle %d\n", _get_proctime() ); 2333 1995 2334 1996 // initialises the FAT 2335 1997 _fat_init( IOC_BOOT_MODE ); 2336 1998 2337 _puts("\n[BOOT] Fat initialised at cycle "); 2338 _putd(_get_proctime()); 2339 _puts("\n"); 2340 // Load the map.bin file into memory and check it 1999 _printf("\n[BOOT] FAT initialised at cycle %d\n", _get_proctime() ); 2000 2001 // Load the map.bin file into memory 2341 2002 boot_mapping_init(); 2342 2003 2343 _puts("\n[BOOT] Mapping \""); 2344 _puts( header->name ); 2345 _puts("\" loaded at cycle "); 2346 _putd(_get_proctime()); 2347 _puts("\n"); 2348 2349 _barrier_init(&barrier_boot, X_SIZE*Y_SIZE); 2350 2351 for ( clusterid = 1 ; clusterid < X_SIZE*Y_SIZE ; clusterid++ ) 2352 { 2353 unsigned int x = cluster[clusterid].x; 2354 unsigned int y = cluster[clusterid].y; 2355 unsigned int cluster_xy = (x<<Y_WIDTH) + y; 2356 2357 _xcu_send_wti_paddr( cluster_xy, 0, (unsigned int)boot_entry ); 2358 } 2359 } 2360 //Parallel phase to construct the ptab by each processor[x][y][0] 2361 if( (gpid & ((1 << P_WIDTH) -1)) == 0) 2362 { 2363 // Initializes the physical memory allocators 2364 boot_pmem_init(); 2365 // Build ge tables 2366 boot_ptabs_init(); 2367 //wait for all processors finished the work 2368 _barrier_wait(&barrier_boot); 2369 2370 if( gpid ) while( boot_init_ok == 0); 2371 } 2372 2373 if ( gpid == 0 ) // only Processor 0 does it 2374 { 2375 _puts("\n[BOOT] Physical memory allocators and Page table initialized at cycle "); 2376 _putd(_get_proctime()); 2377 _puts("\n"); 2378 2379 // Activate MMU for proc [0,0,0] 2380 _set_mmu_ptpr( (unsigned int)(_ptabs_paddr[0][0][0]>>13) ); 2004 _printf("\n[BOOT] Mapping %s loaded at cycle %d\n", 2005 header->name , _get_proctime() ); 2006 2007 // initialises the barrier for all clusters containing processors 2008 unsigned int nclusters = 0; 2009 for ( cid = 0 ; cid < X_SIZE*Y_SIZE ; cid++ ) 2010 { 2011 if ( cluster[cid].procs ) nclusters++ ; 2012 } 2013 2014 _simple_barrier_init( &_barrier_all_clusters , nclusters ); 2015 2016 // wake up all processors P[x][y][0] 2017 for ( cid = 1 ; cid < X_SIZE*Y_SIZE ; cid++ ) 2018 { 2019 unsigned int x = cluster[cid].x; 2020 unsigned int y = cluster[cid].y; 2021 unsigned int cluster_xy = (x << Y_WIDTH) + y; 2022 2023 if ( cluster[cid].procs ) 2024 { 2025 unsigned long long paddr = (((unsigned long long)cluster_xy)<<32) + 2026 SEG_XCU_BASE + XCU_REG( XCU_WTI_REG , 0 ); 2027 2028 _physical_write( paddr , (unsigned int)boot_entry ); 2029 } 2030 } 2031 2032 _printf("\n[BOOT] Processors P[x,y,0] start at cycle %d\n", _get_proctime() ); 2033 } 2034 2035 // Phase TWO : All processors P[x][y][0] execute it in parallel 2036 if( lpid == 0 ) 2037 { 2038 // Initializes physical memory allocator in cluster[cx][cy] 2039 boot_pmem_init( cx , cy ); 2040 2041 // Build page table in cluster[cx][cy] 2042 boot_ptab_init( cx , cy ); 2043 2044 ////////////////////////////////////////////// 2045 _simple_barrier_wait( &_barrier_all_clusters ); 2046 ////////////////////////////////////////////// 2047 2048 // P[0][0][0] complete page tables with vsegs 2049 // mapped in clusters without processors 2050 if ( gpid == 0 ) 2051 { 2052 // complete page tables initialisation 2053 boot_ptab_extend(); 2054 2055 _printf("\n[BOOT] Physical memory allocators and page tables" 2056 " initialized at cycle %d\n", _get_proctime() ); 2057 } 2058 2059 ////////////////////////////////////////////// 2060 _simple_barrier_wait( &_barrier_all_clusters ); 2061 ////////////////////////////////////////////// 2062 2063 // All processors P[x,y,0] activate MMU (using local PTAB) 2064 _set_mmu_ptpr( (unsigned int)(_ptabs_paddr[0][cx][cy]>>13) ); 2381 2065 _set_mmu_mode( 0xF ); 2382 2383 _puts("\n[BOOT] Processor[0,0,0] : MMU activation at cycle ");2384 _putd(_get_proctime());2385 _puts("\n");2386 2387 // Initialise private vobjs in vspaces2388 boot_vobjs_init();2389 2390 _puts("\n[BOOT] Private vobjs initialised at cycle ");2391 _putd(_get_proctime());2392 _puts("\n");2393 2394 // Initialise schedulers2395 boot_schedulers_init();2396 2397 _puts("\n[BOOT] Schedulers initialised at cycle ");2398 _putd(_get_proctime());2399 _puts("\n");2400 2066 2401 // Set CP0_SCHED register for proc [0,0,0] 2402 _set_sched( (unsigned int)_schedulers[0][0][0] ); 2403 2404 // Initialise non replicated peripherals 2405 boot_peripherals_init(); 2406 2407 _puts("\n[BOOT] Non replicated peripherals initialised at cycle "); 2408 _putd(_get_proctime()); 2409 _puts("\n"); 2410 2411 // Loading all .elf files 2412 boot_elf_load(); 2413 2414 // wake up the processors which has constructed the ptab before 2415 boot_init_ok = 1; 2416 2417 for ( clusterid = 0 ; clusterid < X_SIZE*Y_SIZE ; clusterid++ ) 2418 { 2419 unsigned int nprocs = cluster[clusterid].procs; 2420 unsigned int x = cluster[clusterid].x; 2421 unsigned int y = cluster[clusterid].y; 2422 unsigned int cluster_xy = (x<<Y_WIDTH) + y; 2423 2424 for ( p = 1 ; p < nprocs; p++ ) 2067 // Each processor P[x,y,0] initialises all schedulers in cluster[x,y] 2068 boot_scheduler_init( cx , cy ); 2069 2070 // Each processor P[x][y][0] initialises its CP0_SCHED register 2071 _set_sched( (unsigned int)_schedulers[cx][cy][0] ); 2072 2073 ////////////////////////////////////////////// 2074 _simple_barrier_wait( &_barrier_all_clusters ); 2075 ////////////////////////////////////////////// 2076 2077 // Processor P[0,0,0] completes schedulers with PIC-WTI 2078 // initialises external peripherals and load .elf files. 2079 if ( gpid == 0 ) 2080 { 2081 // complete schedulers initialisation 2082 boot_pic_wti_init(); 2083 2084 _printf("\n[BOOT] Schedulers initialised at cycle %d\n", _get_proctime() ); 2085 2086 // initialize non replicated peripherals 2087 boot_peripherals_init(); 2088 2089 _printf("\n[BOOT] Peripherals initialised at cycle %d\n", _get_proctime() ); 2090 2091 // Loading all .elf files 2092 boot_elf_load(); 2093 } 2094 /* 2095 // Each processor P[x][y][0] checks sequencially its local page table 2096 unsigned int seq_x; 2097 unsigned int seq_y; 2098 for ( seq_x = 0 ; seq_x < X_SIZE ; seq_x++ ) 2099 { 2100 for ( seq_y = 0 ; seq_y < Y_SIZE ; seq_y++ ) 2425 2101 { 2426 _xcu_send_wti( cluster_xy, p, (unsigned int)boot_entry ); 2102 if ( (cx == seq_x) && (cy == seq_y) ) boot_ptab_check( cx , cy ); 2103 2104 ////////////////////////////////////////////// 2105 _simple_barrier_wait( &_barrier_all_clusters ); 2106 ////////////////////////////////////////////// 2427 2107 } 2428 2108 } 2429 } // end monoprocessor boot 2430 2431 /////////////////////////////////////////////////////////////////////////////// 2432 // Parallel execution starts actually here 2433 /////////////////////////////////////////////////////////////////////////////// 2434 2435 // all processor initialise the SCHED register 2436 // from the _schedulers[x][y][lpid array] 2437 unsigned int cluster_xy = gpid >> P_WIDTH; 2438 unsigned int lpid = gpid & ((1<<P_WIDTH)-1); 2439 unsigned int x = cluster_xy >> Y_WIDTH; 2440 unsigned int y = cluster_xy & ((1<<Y_WIDTH)-1); 2441 _set_sched( (unsigned int)_schedulers[x][y][lpid] ); 2442 2443 // all processors (but Proc[0,0,0]) activate MMU 2444 if ( gpid != 0 ) 2445 { 2446 _set_mmu_ptpr( (unsigned int)(_ptabs_paddr[0][x][y]>>13) ); 2109 */ 2110 ////////////////////////////////////////////// 2111 _simple_barrier_wait( &_barrier_all_clusters ); 2112 ////////////////////////////////////////////// 2113 2114 // each processor P[x][y][0] wake up other processors in same cluster 2115 unsigned int cluster_xy = (cx << Y_WIDTH) + cy; 2116 unsigned int p; 2117 for ( p = 1 ; p < cluster[cluster_id].procs ; p++ ) 2118 { 2119 _xcu_send_wti( cluster_xy , p , (unsigned int)boot_entry ); 2120 } 2121 2122 if ( gpid == 0 ) // only P[0][0][0] makes display 2123 _printf("\n[BOOT] All processors start at cycle %d\n", _get_proctime() ); 2124 } 2125 2126 // Other processors than P[x][y][0] activate MMU (using local PTAB) 2127 if ( lpid != 0 ) 2128 { 2129 _set_mmu_ptpr( (unsigned int)(_ptabs_paddr[0][cx][cy]>>13) ); 2447 2130 _set_mmu_mode( 0xF ); 2448 2131 } 2449 2132 2450 // all processors reset BEV bit in the status register to use 2451 // the GIET_VM exception handler instead of the PRELOADER exception handler 2133 // All processors set CP0_SCHED register 2134 _set_sched( (unsigned int)_schedulers[cx][cy][lpid] ); 2135 2136 // All processors reset BEV bit in SR to use GIET_VM exception handler 2452 2137 _set_sr( 0 ); 2453 2138 2454 // all processors jump to kernel_init 2455 // using the address defined in the giet_vsegs.ld file 2139 // All processors jump to kernel_init 2456 2140 unsigned int kernel_entry = (unsigned int)&kernel_init_vbase; 2457 2141 asm volatile( "jr %0" ::"r"(kernel_entry) ); -
soft/giet_vm/giet_boot/boot.ld
r366 r493 30 30 seg_boot_data : 31 31 { 32 *(.bootdata) 33 *(.fatdata) 32 *(.kdata) 34 33 } 35 34 } -
soft/giet_vm/giet_boot/boot_entry.S
r490 r493 1 1 /* 2 * file : boot .S2 * file : boot_entry.S 3 3 * date : 01/17/2014 4 4 * author : Cesar Fuguet & Alain Greiner & Hao Liu … … 19 19 * to the boot_init() fuction defined in the boot.c file. 20 20 * 21 * - each processor [x][y][0] uses a larger stack: 1,25 Kbytes.22 * - Other processors use a smaller stack: 256bytes.23 * => the SEG_BOOT_STACK_SIZE cannot be smaller 512 Kytes.24 * (256*(1024+256) + (1024 - 256) * 256 = 512 Kbytes = 0x80000)21 * - each processor P[x,y,0] uses a larger stack: 1,25 Kbytes. 22 * - Other processors use a smaller stack: 0,25 Kbytes. 23 * => the SEG_BOOT_STACK_SIZE cannot be smaller than 24 * 256 * (1024 + 256) + (1024 - 256) * 256 = 512 Kbytes 25 25 */ 26 26 … … 38 38 boot_entry: 39 39 40 41 /* All processors compute proc_id = (cluster_id * NBPROCS) + lpid */42 /* where cluster_id = (x * Y_SIZE) + y */43 40 /* The (x,y,lpid) values are obtained from the processor CP0 register, */ 44 /* where proc_xyl == (((x<<4) + y) * NB_PROCS_MAX) + lpid */ 45 /* (proc_id is a "continuous" index, while proc_xyl is a "fixed format" index */ 46 41 /* where proc_id == (((x<<Y_WIDTH) + y)<<P_WIDTH) + lpid (fixed format) */ 42 /* The continuous cluster index is computed as cluster_id = (x * Y_SIZE) + y */ 47 43 48 44 mfc0 k0, CP0_PROCID 49 andi k0, k0, 0xFFF /* k0 <= proc_ xyl*/45 andi k0, k0, 0xFFF /* k0 <= proc_id */ 50 46 andi t1, k0, ((1<<P_WIDTH)-1) /* t1 <= lpid */ 51 47 srl t2, k0, P_WIDTH /* t2 <= cluster_xy */ … … 54 50 la t6, Y_SIZE /* t6 <= Y_SIZE */ 55 51 multu t3, t6 56 mflo t5 52 mflo t5 /* t5 <= x * Y_SIZE */ 57 53 addu t5, t5, t4 /* t5 <= cluster_id */ 58 li t6, 0x100 * (NB_PROCS_MAX - 1) + 0x500 /* stack size per cluster */ 54 55 /* All processors initializes stack pointer, depending on x,y,lpid */ 56 /* Processors P[x,y,0] : stack size = 1,25 Kbytes */ 57 /* Other processors : stack size = 0,25 Kbytes 58 /* In each cluster, the total stack size is NB_PROCS_MAX-1)*0x100 + 0x500 */ 59 60 li t6, (NB_PROCS_MAX-1) * 0x100 + 0x500 /* t6 <= cluster_size */ 59 61 multu t6, t5 60 mflo t7 61 62 /* All processors initializes stack pointer, depending on proc_id */ 63 64 la k0, SEG_BOOT_STACK_BASE 65 addu k0, k0, t7 66 li k1, 0x500 /* k1 <= local P0 stack size == 1,25 Kbytes */ 67 addu sp, k0, k1 /* P0 stack from base to (base + stack size * cluster_id + 1,25K ) */ 68 69 li k1, 0x100 /* k1 <= Pi stack size == 256 bytes */ 70 multu k1, t1 71 mflo k0 /* k0 <= 256 * proc_id */ 72 addu sp, sp, k0 /* Pi stacks from base + stack size * cluster_id + 1,25K + proc_id*256 */ 73 62 mflo t7 /* t7 <= cluster_size * cluster_id */ 63 la k0, SEG_BOOT_STACK_BASE 64 addu k0, k0, t7 /* k0 <= stack base in cluster */ 65 li k1, 0x500 /* k1 <= 1,25 Kbytes */ 66 addu sp, k0, k1 /* P[x,y,0] stack top */ 67 li k1, 0x100 /* k1 <= 0,25 bytes */ 68 multu k1, t1 69 mflo k0 /* k0 <= 256 * lpid */ 70 addu sp, sp, k0 /* P[x,y,lpid] stack top */ 74 71 75 72 /* All processors jump to the boot_init function */
Note: See TracChangeset
for help on using the changeset viewer.