Changeset 238 for soft/giet_vm/boot
- Timestamp:
- May 29, 2013, 1:24:09 AM (12 years ago)
- Location:
- soft/giet_vm/boot
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
soft/giet_vm/boot/boot_init.c
r236 r238 7 7 // The boot_init.c file is part of the GIET-VM nano-kernel. 8 8 // This code is executed in the boot phase by proc[0] to initialize the 9 // 9 // peripherals and the kernel data structures: 10 10 // - pages tables for the various vspaces 11 11 // - shedulers for processors (including the tasks contexts and interrupt vectors) 12 // 13 // This nano-kernel has been written for the MIPS32 processor. 14 // The virtual adresses are on 32 bits and use the (unsigned int) type, but the 15 // physicals addresses can have up to 40 bits, and use the (unsigned long long) type. 12 16 // 13 17 // The GIET-VM uses the paged virtual memory and the MAPPING_INFO binary file … … 20 24 // The MAPPING_INFO binary data structure must be loaded in the the seg_boot_mapping 21 25 // segment (at address seg_mapping_base). 22 // This MAPPING_INFO data structure defines both the hardware architecture 23 // and the mapping: 24 // - physical segmentation of the physical address space, 25 // - virtual spaces definition (one multi-task application per vspace), 26 // - placement of virtual objects (vobj) in the virtual segments (vseg). 27 // - placement of virtual segments (vseg) in the physical segments (pseg). 28 // - placement of tasks on the processors, 26 // This MAPPING_INFO data structure defines 27 // - the hardware architecture: number of clusters, number or processors, 28 // size of the memory segments, and peripherals in each cluster. 29 // - The structure of the various multi-threaded software applications: 30 // number of tasks, communication channels. 31 // - The mapping: placement of virtual objects (vobj) in the virtual segments (vseg), 32 // placement of virtual segments (vseg) in the physical segments (pseg), placement 33 // of software tasks on the processors, 29 34 // 30 35 // The page table are statically build in the boot phase, and they do not … … 35 40 // The max number of virtual spaces (GIET_NB_VSPACE_MAX) is a configuration parameter. 36 41 // 37 // Each page table (one page table per virtual space) is monolithic, and 38 // contains one PT1 and(GIET_NB_PT2_MAX) PT2s. The PT1 is addressed using the ix1 field42 // Each page table (one page table per virtual space) is monolithic, and contains 43 // one PT1 and up to (GIET_NB_PT2_MAX) PT2s. The PT1 is addressed using the ix1 field 39 44 // (11 bits) of the VPN, and the selected PT2 is addressed using the ix2 field (9 bits). 40 // - PT1[2048] : a first 8K aligned array of unsigned int, indexed by the(ix1) field of VPN.45 // - PT1[2048] : a first 8K aligned array of unsigned int, indexed by (ix1) field of VPN. 41 46 // Each entry in the PT1 contains a 32 bits PTD. The MSB bit PTD[31] is 42 47 // the PTD valid bit, and LSB bits PTD[19:0] are the 20 MSB bits of the physical base … … 44 49 // The PT1 contains 2048 PTD of 4 bytes => 8K bytes. 45 50 // - PT2[1024][GIET_NB_PT2_MAX] : an array of array of unsigned int. 46 // Each PT2[1024] must be 4K aligned, andeach entry in a PT2 contains two unsigned int:51 // Each PT2[1024] must be 4K aligned, each entry in a PT2 contains two unsigned int: 47 52 // the first word contains the protection flags, and the second word contains the PPN. 48 53 // Each PT2 contains 512 PTE2 of 8bytes => 4K bytes. … … 64 69 #include <stdarg.h> 65 70 66 67 71 #if !defined(NB_CLUSTERS) 68 72 # error The NB_CLUSTERS value must be defined in the 'giet_config.h' file ! … … 79 83 //////////////////////////////////////////////////////////////////////////// 80 84 // Global variables for boot code 81 // As both the page tables and the schedulers are physically distributed, 82 // these global variables are just arrays of pointers. 85 // Both the page tables for the various virtual spaces, and the schedulers 86 // for the processors are physically distributed on the clusters. 87 // These global variables are just arrays of pointers. 83 88 //////////////////////////////////////////////////////////////////////////// 84 89 85 // Page table pointers array86 pa ge_table_t * boot_ptabs_vaddr[GIET_NB_VSPACE_MAX];87 page_table_t * boot_ptabs_paddr[GIET_NB_VSPACE_MAX];88 89 // Scheduler pointers array 90 static_scheduler_t * boot_schedulers_paddr[NB_CLUSTERS * NB_PROCS_MAX];90 // Page table addresses arrays 91 paddr_t boot_ptabs_paddr[GIET_NB_VSPACE_MAX]; 92 unsigned int boot_ptabs_vaddr[GIET_NB_VSPACE_MAX]; 93 94 // Scheduler pointers array (virtual addresses) 95 static_scheduler_t* boot_schedulers[NB_CLUSTERS * NB_PROCS_MAX]; 91 96 92 97 // Next free PT2 index array … … 102 107 // boot_procid() 103 108 ////////////////////////////////////////////////////////////////////////////// 104 inline unsigned int boot_procid() { 109 inline unsigned int boot_procid() 110 { 105 111 unsigned int ret; 106 112 asm volatile ("mfc0 %0, $15, 1":"=r" (ret)); … … 108 114 } 109 115 110 111 116 ////////////////////////////////////////////////////////////////////////////// 112 117 // boot_proctime() 113 118 ////////////////////////////////////////////////////////////////////////////// 114 inline unsigned int boot_proctime() { 119 inline unsigned int boot_proctime() 120 { 115 121 unsigned int ret; 116 122 asm volatile ("mfc0 %0, $9":"=r" (ret)); … … 118 124 } 119 125 120 121 126 ////////////////////////////////////////////////////////////////////////////// 122 127 // boot_exit() 123 128 ////////////////////////////////////////////////////////////////////////////// 124 void boot_exit() { 125 while (1) { 126 asm volatile ("nop"); 127 } 128 } 129 129 void boot_exit() 130 { 131 while (1) { asm volatile ("nop"); } 132 } 130 133 131 134 ////////////////////////////////////////////////////////////////////////////// … … 134 137 // in all task contexts (when the task has never been executed. 135 138 /////////////////////////////////"///////////////////////////////////////////// 136 void boot_eret() { 139 void boot_eret() 140 { 137 141 asm volatile ("eret"); 138 142 } 139 143 140 141 ////////////////////////////////////////////////////////////////////////////// 142 // boot_scheduler_set_context() 143 // This function set a context slot in a scheduler, after a temporary 144 // desactivation of the DTLB (because we use the scheduler physical address). 145 // - gpid : global processor/scheduler index 146 // - ltid : local task index 147 // - slotid : context slot index 148 // - value : value to be written 149 ////////////////////////////////////////////////////////////////////////////// 150 inline void boot_scheduler_set_context(unsigned int gpid, 151 unsigned int ltid, 152 unsigned int slotid, 153 unsigned int value) { 154 // get scheduler physical address 155 static_scheduler_t * psched = boot_schedulers_paddr[gpid]; 156 157 // get slot physical address 158 unsigned int * pslot = &(psched->context[ltid][slotid]); 159 160 asm volatile ("li $26, 0xB \n" 161 "mtc2 $26, $1 \n" /* desactivate DTLB */ 162 "sw %1, 0(%0) \n" /* *pslot <= value */ 163 "li $26, 0xF \n" 164 "mtc2 $26, $1 \n" /* activate DTLB */ 144 //////////////////////////////////////////////////////////////////////////// 145 // boot_physical_read() 146 // This function makes a physical read access to a 32 bits word in memory, 147 // after a temporary DTLB de-activation and paddr extension. 148 //////////////////////////////////////////////////////////////////////////// 149 unsigned int boot_physical_read(paddr_t paddr) 150 { 151 unsigned int value; 152 unsigned int lsb = (unsigned int)paddr; 153 unsigned int msb = (unsigned int)(paddr >> 32); 154 155 asm volatile( 156 "mfc2 $2, $1 \n" /* $2 <= MMU_MODE */ 157 "andi $3, $2, 0xb \n" 158 "mtc2 $3, $1 \n" /* DTLB off */ 159 160 "mtc2 %2, $24 \n" /* PADDR_EXT <= msb */ 161 "lw %0, 0(%1) \n" /* value <= *paddr */ 162 "mtc2 $0, $24 \n" /* PADDR_EXT <= 0 */ 163 164 "mtc2 $2, $1 \n" /* restore MMU_MODE */ 165 : "=r" (value) 166 : "r" (lsb), "r" (msb) 167 : "$2", "$3"); 168 return value; 169 } 170 171 //////////////////////////////////////////////////////////////////////////// 172 // boot_physical_write() 173 // This function makes a physical write access to a 32 bits word in memory, 174 // after a temporary DTLB de-activation and paddr extension. 175 //////////////////////////////////////////////////////////////////////////// 176 void boot_physical_write(paddr_t paddr, 177 unsigned int value) 178 { 179 unsigned int lsb = (unsigned int)paddr; 180 unsigned int msb = (unsigned int)(paddr >> 32); 181 182 asm volatile( 183 "mfc2 $2, $1 \n" /* $2 <= MMU_MODE */ 184 "andi $3, $2, 0xb \n" 185 "mtc2 $3, $1 \n" /* DTLB off */ 186 187 "mtc2 %2, $24 \n" /* PADDR_EXT <= msb */ 188 "sw %0, 0(%1) \n" /* *paddr <= value */ 189 "mtc2 $0, $24 \n" /* PADDR_EXT <= 0 */ 190 191 "mtc2 $2, $1 \n" /* restore MMU_MODE */ 165 192 : 166 :"r" (pslot), "r"(value) 167 :"$26"); 168 } 169 170 171 ////////////////////////////////////////////////////////////////////////////// 172 // boot_scheduler_set_itvector() 173 // This function set an interrupt vector slot in a scheduler, after a temporary 174 // desactivation of the DTLB (because we use the scheduler physical address). 175 // - gpid : global processor/scheduler index 176 // - slotid : context slot index 177 // - value : value to be written 178 ////////////////////////////////////////////////////////////////////////////// 179 inline void boot_scheduler_set_itvector(unsigned int gpid, 180 unsigned int slotid, 181 unsigned int value) { 182 // get scheduler physical address 183 static_scheduler_t * psched = boot_schedulers_paddr[gpid]; 184 185 // get slot physical address 186 unsigned int * pslot = &(psched->interrupt_vector[slotid]); 187 188 asm volatile ("li $26, 0xB \n" 189 "mtc2 $26, $1 \n" /* desactivate DTLB */ 190 "sw %1, 0(%0) \n" /* *pslot <= value */ 191 "li $26, 0xF \n" 192 "mtc2 $26, $1 \n" /* activate DTLB */ 193 : 194 :"r" (pslot), "r"(value) 195 :"$26"); 196 } 197 198 199 ////////////////////////////////////////////////////////////////////////////// 200 // boot_scheduler_get_itvector() 201 // This function get an interrupt vector slot in a scheduler, after a temporary 202 // desactivation of the DTLB (because we use the scheduler physical address). 203 // - gpid : global processor/scheduler index 204 // - slotid : context slot index 205 // - return the content of the slot 206 ////////////////////////////////////////////////////////////////////////////// 207 unsigned int boot_scheduler_get_itvector(unsigned int gpid, unsigned int slotid) { 208 unsigned int value; 209 210 // get scheduler physical address 211 static_scheduler_t * psched = boot_schedulers_paddr[gpid]; 212 213 // get slot physical address 214 unsigned int * pslot = &(psched->interrupt_vector[slotid]); 215 216 asm volatile ("li $26, 0xB \n" 217 "mtc2 $26, $1 \n" /* desactivate DTLB */ 218 "lw %0, 0(%1) \n" /* *pslot <= value */ 219 "li $26, 0xF \n" 220 "mtc2 $26, $1 \n" /* activate DTLB */ 221 :"=r" (value) 222 :"r"(pslot) 223 :"$26"); 224 return value; 225 } 226 227 228 ////////////////////////////////////////////////////////////////////////////// 229 // boot_scheduler_get_tasks() 230 // This function returns the "tasks" field of a scheduler, after temporary 231 // desactivation of the DTLB (because we use the scheduler physical address). 232 // - gpid : global processor/scheduler index 233 ////////////////////////////////////////////////////////////////////////////// 234 inline unsigned int boot_scheduler_get_tasks(unsigned int gpid) { 235 unsigned int ret; 236 237 // get scheduler physical address 238 static_scheduler_t * psched = boot_schedulers_paddr[gpid]; 239 240 // get tasks physical address 241 unsigned int * ptasks = &(psched->tasks); 242 243 asm volatile ("li $26, 0xB \n" 244 "mtc2 $26, $1 \n" /* desactivate DTLB */ 245 "lw %0, 0(%1) \n" /* ret <= *ptasks */ 246 "li $26, 0xF \n" 247 "mtc2 $26, $1 \n" /* activate DTLB */ 248 :"=r" (ret) 249 :"r"(ptasks) 250 :"$26"); 251 return ret; 252 } 253 254 255 ////////////////////////////////////////////////////////////////////////////// 256 // boot_scheduler_set_tasks() 257 // This function set the "tasks" field of a scheduler, after temporary 258 // desactivation of the DTLB (because we use the scheduler physical address). 259 // - gpid : global processor/scheduler index 260 // - value : value to be written 261 ////////////////////////////////////////////////////////////////////////////// 262 inline void boot_scheduler_set_tasks(unsigned int gpid, unsigned int value) { 263 // get scheduler physical address 264 static_scheduler_t * psched = boot_schedulers_paddr[gpid]; 265 266 // get tasks physical address 267 unsigned int * ptasks = &(psched->tasks); 268 269 asm volatile ("li $26, 0xB \n" 270 "mtc2 $26, $1 \n" /* desactivate DTLB */ 271 "sw %1, 0(%0) \n" /* *ptasks <= value */ 272 "li $26, 0xF \n" 273 "mtc2 $26, $1 \n" /* activate DTLB */ 274 : 275 :"r" (ptasks), "r"(value) 276 :"$26"); 277 } 278 279 280 ////////////////////////////////////////////////////////////////////////////// 281 // boot_scheduler_set_current() 282 // This function set the "current" field of a scheduler, after temporary 283 // desactivation of the DTLB (because we use the scheduler physical address). 284 // - gpid : global processor/scheduler index 285 // - value : value to be written 286 ////////////////////////////////////////////////////////////////////////////// 287 inline void boot_scheduler_set_current(unsigned int gpid, unsigned int value) { 288 // get scheduler physical address 289 static_scheduler_t *psched = boot_schedulers_paddr[gpid]; 290 291 // get tasks physical address 292 unsigned int * pcur = &(psched->current); 293 294 asm volatile ("li $26, 0xB \n" 295 "mtc2 $26, $1 \n" /* desactivate DTLB */ 296 "sw %1, 0(%0) \n" /* *pcur <= value */ 297 "li $26, 0xF \n" 298 "mtc2 $26, $1 \n" /* activate DTLB */ 299 : 300 :"r" (pcur), "r"(value) 301 :"$26"); 302 } 303 193 : "r" (value), "r" (lsb), "r" (msb) 194 : "$2", "$3"); 195 } 304 196 305 197 ////////////////////////////////////////////////////////////////////////////// … … 307 199 // This function set a new value for the MMU PTPR register. 308 200 ////////////////////////////////////////////////////////////////////////////// 309 inline void boot_set_mmu_ptpr(unsigned int val) { 201 inline void boot_set_mmu_ptpr(unsigned int val) 202 { 310 203 asm volatile ("mtc2 %0, $0"::"r" (val)); 311 204 } 312 313 205 314 206 ////////////////////////////////////////////////////////////////////////////// … … 316 208 // This function set a new value for the MMU MODE register. 317 209 ////////////////////////////////////////////////////////////////////////////// 318 inline void boot_set_mmu_mode(unsigned int val) { 210 inline void boot_set_mmu_mode(unsigned int val) 211 { 319 212 asm volatile ("mtc2 %0, $1"::"r" (val)); 320 213 } 321 322 214 323 215 //////////////////////////////////////////////////////////////////////////// 324 216 // boot_puts() 325 // (it uses TTY0)217 // display a string on TTY0 326 218 //////////////////////////////////////////////////////////////////////////// 327 void boot_puts(const char * buffer) { 219 void boot_puts(const char * buffer) 220 { 328 221 unsigned int *tty_address = (unsigned int *) &seg_tty_base; 329 222 unsigned int n; 330 223 331 for (n = 0; n < 100; n++) { 332 if (buffer[n] == 0) { 333 break; 334 } 224 for (n = 0; n < 100; n++) 225 { 226 if (buffer[n] == 0) break; 335 227 tty_address[TTY_WRITE] = (unsigned int) buffer[n]; 336 228 } 337 229 } 338 339 230 340 231 //////////////////////////////////////////////////////////////////////////// 341 232 // boot_putx() 342 // (it uses TTY0)233 // display a 32 bits unsigned int as an hexadecimal string on TTY0 343 234 //////////////////////////////////////////////////////////////////////////// 344 void boot_putx(unsigned int val) { 235 void boot_putx(unsigned int val) 236 { 345 237 static const char HexaTab[] = "0123456789ABCDEF"; 346 238 char buf[11]; … … 351 243 buf[10] = 0; 352 244 353 for (c = 0; c < 8; c++) { 245 for (c = 0; c < 8; c++) 246 { 354 247 buf[9 - c] = HexaTab[val & 0xF]; 355 248 val = val >> 4; … … 358 251 } 359 252 253 //////////////////////////////////////////////////////////////////////////// 254 // boot_putl() 255 // display a 64 bits unsigned long as an hexadecimal string on TTY0 256 //////////////////////////////////////////////////////////////////////////// 257 void boot_putl(paddr_t val) 258 { 259 static const char HexaTab[] = "0123456789ABCDEF"; 260 char buf[19]; 261 unsigned int c; 262 263 buf[0] = '0'; 264 buf[1] = 'x'; 265 buf[18] = 0; 266 267 for (c = 0; c < 16; c++) 268 { 269 buf[17 - c] = HexaTab[(unsigned int)val & 0xF]; 270 val = val >> 4; 271 } 272 boot_puts(buf); 273 } 360 274 361 275 //////////////////////////////////////////////////////////////////////////// 362 276 // boot_putd() 363 // (it uses TTY0)277 // display a 32 bits unsigned int as a decimal string on TTY0 364 278 //////////////////////////////////////////////////////////////////////////// 365 void boot_putd(unsigned int val) { 279 void boot_putd(unsigned int val) 280 { 366 281 static const char DecTab[] = "0123456789"; 367 282 char buf[11]; … … 371 286 buf[10] = 0; 372 287 373 for (i = 0; i < 10; i++) { 374 if ((val != 0) || (i == 0)) { 288 for (i = 0; i < 10; i++) 289 { 290 if ((val != 0) || (i == 0)) 291 { 375 292 buf[9 - i] = DecTab[val % 10]; 376 293 first = 9 - i; 377 294 } 378 else { 295 else 296 { 379 297 break; 380 298 } … … 384 302 } 385 303 386 387 304 ///////////////////////////////////////////////////////////////////////////// 388 305 // mapping_info data structure access functions 389 306 ///////////////////////////////////////////////////////////////////////////// 390 inline mapping_cluster_t *boot_get_cluster_base(mapping_header_t * header) { 307 inline mapping_cluster_t *boot_get_cluster_base(mapping_header_t * header) 308 { 391 309 return (mapping_cluster_t *) ((char *) header + MAPPING_HEADER_SIZE); 392 310 } 393 394 395 311 ///////////////////////////////////////////////////////////////////////////// 396 inline mapping_pseg_t *boot_get_pseg_base(mapping_header_t * header) { 312 inline mapping_pseg_t *boot_get_pseg_base(mapping_header_t * header) 313 { 397 314 return (mapping_pseg_t *) ((char *) header + 398 315 MAPPING_HEADER_SIZE + 399 316 MAPPING_CLUSTER_SIZE * header->clusters); 400 317 } 401 402 403 318 ///////////////////////////////////////////////////////////////////////////// 404 inline mapping_vspace_t *boot_get_vspace_base(mapping_header_t * header) { 319 inline mapping_vspace_t *boot_get_vspace_base(mapping_header_t * header) 320 { 405 321 return (mapping_vspace_t *) ((char *) header + 406 322 MAPPING_HEADER_SIZE + … … 408 324 MAPPING_PSEG_SIZE * header->psegs); 409 325 } 410 411 412 326 ///////////////////////////////////////////////////////////////////////////// 413 inline mapping_vseg_t *boot_get_vseg_base(mapping_header_t * header) { 327 inline mapping_vseg_t *boot_get_vseg_base(mapping_header_t * header) 328 { 414 329 return (mapping_vseg_t *) ((char *) header + 415 330 MAPPING_HEADER_SIZE + … … 418 333 MAPPING_VSPACE_SIZE * header->vspaces); 419 334 } 420 421 422 335 ///////////////////////////////////////////////////////////////////////////// 423 inline mapping_vobj_t *boot_get_vobj_base(mapping_header_t * header) { 336 inline mapping_vobj_t *boot_get_vobj_base(mapping_header_t * header) 337 { 424 338 return (mapping_vobj_t *) ((char *) header + 425 339 MAPPING_HEADER_SIZE + … … 429 343 MAPPING_VSEG_SIZE * header->vsegs); 430 344 } 431 432 433 345 ///////////////////////////////////////////////////////////////////////////// 434 inline mapping_task_t *boot_get_task_base(mapping_header_t * header) { 346 inline mapping_task_t *boot_get_task_base(mapping_header_t * header) 347 { 435 348 return (mapping_task_t *) ((char *) header + 436 349 MAPPING_HEADER_SIZE + … … 441 354 MAPPING_VOBJ_SIZE * header->vobjs); 442 355 } 443 444 445 356 ///////////////////////////////////////////////////////////////////////////// 446 inline mapping_proc_t *boot_get_proc_base(mapping_header_t * header) { 357 inline mapping_proc_t *boot_get_proc_base(mapping_header_t * header) 358 { 447 359 return (mapping_proc_t *) ((char *) header + 448 360 MAPPING_HEADER_SIZE + … … 454 366 MAPPING_TASK_SIZE * header->tasks); 455 367 } 456 457 458 368 ///////////////////////////////////////////////////////////////////////////// 459 inline mapping_irq_t *boot_get_irq_base(mapping_header_t * header) { 369 inline mapping_irq_t *boot_get_irq_base(mapping_header_t * header) 370 { 460 371 return (mapping_irq_t *) ((char *) header + 461 372 MAPPING_HEADER_SIZE + … … 468 379 MAPPING_PROC_SIZE * header->procs); 469 380 } 470 471 472 381 ///////////////////////////////////////////////////////////////////////////// 473 inline mapping_coproc_t *boot_get_coproc_base(mapping_header_t * header) { 382 inline mapping_coproc_t *boot_get_coproc_base(mapping_header_t * header) 383 { 474 384 return (mapping_coproc_t *) ((char *) header + 475 385 MAPPING_HEADER_SIZE + … … 483 393 MAPPING_IRQ_SIZE * header->irqs); 484 394 } 485 486 487 395 /////////////////////////////////////////////////////////////////////////////////// 488 inline mapping_cp_port_t *boot_get_cp_port_base(mapping_header_t * header) { 396 inline mapping_cp_port_t *boot_get_cp_port_base(mapping_header_t * header) 397 { 489 398 return (mapping_cp_port_t *) ((char *) header + 490 399 MAPPING_HEADER_SIZE + … … 499 408 MAPPING_COPROC_SIZE * header->coprocs); 500 409 } 501 502 503 410 /////////////////////////////////////////////////////////////////////////////////// 504 inline mapping_periph_t *boot_get_periph_base(mapping_header_t * header) { 411 inline mapping_periph_t *boot_get_periph_base(mapping_header_t * header) 412 { 505 413 return (mapping_periph_t *) ((char *) header + 506 414 MAPPING_HEADER_SIZE + … … 517 425 } 518 426 519 520 427 ////////////////////////////////////////////////////////////////////////////// 521 428 // boot_pseg_get() … … 523 430 // identified by the pseg index. 524 431 ////////////////////////////////////////////////////////////////////////////// 525 mapping_pseg_t *boot_pseg_get(unsigned int seg_id) { 432 mapping_pseg_t *boot_pseg_get(unsigned int seg_id) 433 { 526 434 mapping_header_t * header = (mapping_header_t *) & seg_mapping_base; 527 435 mapping_pseg_t * pseg = boot_get_pseg_base(header); 528 436 529 437 // checking argument 530 if (seg_id >= header->psegs) { 438 if (seg_id >= header->psegs) 439 { 531 440 boot_puts("\n[BOOT ERROR] : seg_id argument too large\n"); 532 441 boot_puts(" in function boot_pseg_get()\n"); … … 535 444 536 445 return &pseg[seg_id]; 537 } // end boot_pseg_get() 538 446 } 539 447 540 448 ////////////////////////////////////////////////////////////////////////////// 541 449 // boot_add_pte() 542 // This function registers a new PTE in the page table pointed450 // This function registers a new PTE in the page table defined 543 451 // by the vspace_id argument, and updates both PT1 and PT2. 544 452 // A new PT2 is used when required. 545 453 // As the set of PT2s is implemented as a fixed size array (no dynamic 546 454 // allocation), this function checks a possible overflow of the PT2 array. 547 //548 // The global parameter is a boolean indicating wether a global vseg is549 // being mapped.550 455 ////////////////////////////////////////////////////////////////////////////// 551 456 void boot_add_pte(unsigned int vspace_id, 552 unsigned int vpn, unsigned int flags, unsigned int ppn) { 457 unsigned int vpn, 458 unsigned int flags, 459 unsigned int ppn, 460 unsigned int verbose) 461 { 553 462 unsigned int ix1; 554 463 unsigned int ix2; 555 unsigned int ptba; // PT2 base address 556 unsigned int pt2_id; // PT2 index 557 unsigned int *pt_flags; // pointer on the pte_flags = &PT2[2*ix2] 558 unsigned int *pt_ppn; // pointer on the pte_ppn = &PT2[2*ix2+1] 464 paddr_t pt1_pbase; // PT1 physical base address 465 paddr_t pt2_pbase; // PT2 physical base address 466 paddr_t pte_paddr; // PTE physucal address 467 unsigned int pt2_id; // PT2 index 468 unsigned int ptd; // PTD : entry in PT1 469 unsigned int max_pt2; // max number of PT2s for a given vspace 559 470 560 471 ix1 = vpn >> 9; // 11 bits … … 562 473 563 474 // check that the boot_max_pt2[vspace_id] has been set 564 unsigned int max_pt2 = boot_max_pt2[vspace_id]; 565 566 if (max_pt2 == 0) { 567 boot_puts("Unfound page table for vspace "); 475 max_pt2 = boot_max_pt2[vspace_id]; 476 477 if (max_pt2 == 0) 478 { 479 boot_puts("Undefined page table for vspace "); 568 480 boot_putd(vspace_id); 569 481 boot_puts("\n"); 570 482 boot_exit(); 571 483 } 572 // get page table physical address 573 page_table_t *pt = boot_ptabs_paddr[vspace_id]; 574 575 if ((pt->pt1[ix1] & PTE_V) == 0) { // set a new PTD in PT1 484 485 // get page table physical base address 486 pt1_pbase = boot_ptabs_paddr[vspace_id]; 487 488 // get ptd in PT1 489 ptd = boot_physical_read( pt1_pbase + 4*ix1 ); 490 491 if ((ptd & PTE_V) == 0) // invalid PTD: compute PT2 base address, 492 // and set a new PTD in PT1 493 { 576 494 pt2_id = boot_next_free_pt2[vspace_id]; 577 if (pt2_id == max_pt2) { 495 if (pt2_id == max_pt2) 496 { 578 497 boot_puts("\n[BOOT ERROR] in boot_add_pte() function\n"); 579 498 boot_puts("the length of the ptab vobj is too small\n"); 580 499 boot_exit(); 581 500 } 582 else { 583 ptba = (unsigned int) pt + PT1_SIZE + PT2_SIZE * pt2_id; 584 pt->pt1[ix1] = PTE_V | PTE_T | (ptba >> 12); 501 else 502 { 503 pt2_pbase = pt1_pbase + PT1_SIZE + PT2_SIZE * pt2_id; 504 ptd = PTE_V | PTE_T | (unsigned int)(pt2_pbase >> 12); 505 boot_physical_write( pt1_pbase + 4*ix1 , ptd); 585 506 boot_next_free_pt2[vspace_id] = pt2_id + 1; 586 507 } 587 508 } 588 else { 589 ptba = pt->pt1[ix1] << 12; 590 } 591 592 // set PTE2 593 pt_flags = (unsigned int *) (ptba + 8 * ix2); 594 pt_ppn = (unsigned int *) (ptba + 8 * ix2 + 4); 595 596 *pt_flags = flags; 597 *pt_ppn = ppn; 598 599 /* 600 if ( vpn == 0x00000300) 601 { 602 boot_puts("vpn = "); 603 boot_putx( vpn ); 604 boot_puts("\n"); 605 boot_puts("pt_flags = "); 606 boot_putx( (unsigned int)pt_flags ); 607 boot_puts("\n"); 608 boot_puts("*pt_flags = "); 609 boot_putx( *pt_flags ); 610 boot_puts("\n"); 611 boot_exit(); 612 } 613 614 if ((*pt_flags & PTE_V) != 0) { // page already mapped 615 boot_puts("\n[BOOT ERROR] double mapping in vspace "); 616 boot_putd(vspace_id); 617 boot_puts(" for vpn = "); 618 boot_putx(vpn); 619 boot_puts("\n"); 620 boot_exit(); 621 } 622 */ 623 } // end boot_add_pte() 509 else // valid PTD: compute PT2 base address 510 { 511 pt2_pbase = ((paddr_t)(ptd & 0x0FFFFFFF)) << 12; 512 } 513 514 // set PTE in PT2 : flags & PPN in two 32 bits words 515 pte_paddr = pt2_pbase + 8*ix2; 516 boot_physical_write( pte_paddr , flags); 517 boot_physical_write( pte_paddr + 4 , ppn); 518 519 if ( verbose ) 520 { 521 boot_puts(" / pt1_pbase = "); 522 boot_putl( pt1_pbase ); 523 boot_puts(" / ptd = "); 524 boot_putl( ptd ); 525 boot_puts(" / pt2_pbase = "); 526 boot_putl( pt2_pbase ); 527 boot_puts(" / pte_paddr = "); 528 boot_putl( pte_paddr ); 529 boot_puts(" / ppn = "); 530 boot_putx( ppn ); 531 boot_puts("/\n"); 532 } 533 534 } // end boot_add_pte() 624 535 625 536 … … 627 538 // This function build the page table for a given vspace. 628 539 // The physical base addresses for all vsegs (global and private) 629 // must have been previously computed .540 // must have been previously computed and stored in the mapping. 630 541 // It initializes the MWMR channels. 631 542 ///////////////////////////////////////////////////////////////////// 632 void boot_vspace_pt_build(unsigned int vspace_id) { 543 void boot_vspace_pt_build(unsigned int vspace_id) 544 { 633 545 unsigned int vseg_id; 634 546 unsigned int npages; … … 637 549 unsigned int flags; 638 550 unsigned int page_id; 551 unsigned int verbose = 0; // can be used to activate trace in add_pte() 639 552 640 553 mapping_header_t * header = (mapping_header_t *) & seg_mapping_base; 641 554 mapping_vspace_t * vspace = boot_get_vspace_base(header); 642 mapping_vseg_t * vseg= boot_get_vseg_base(header);555 mapping_vseg_t * vseg = boot_get_vseg_base(header); 643 556 644 557 // private segments 645 558 for (vseg_id = vspace[vspace_id].vseg_offset; 646 vseg_id < (vspace[vspace_id].vseg_offset + vspace[vspace_id].vsegs); 647 vseg_id++) { 559 vseg_id < (vspace[vspace_id].vseg_offset + vspace[vspace_id].vsegs); 560 vseg_id++) 561 { 648 562 vpn = vseg[vseg_id].vbase >> 12; 649 ppn = vseg[vseg_id].pbase >> 12;563 ppn = (unsigned int)(vseg[vseg_id].pbase >> 12); 650 564 npages = vseg[vseg_id].length >> 12; 651 if ((vseg[vseg_id].length & 0xFFF) != 0) { 652 npages++; 653 } 565 if ((vseg[vseg_id].length & 0xFFF) != 0) npages++; 654 566 655 567 flags = PTE_V; 656 if (vseg[vseg_id].mode & C_MODE_MASK) { 657 flags = flags | PTE_C; 658 } 659 if (vseg[vseg_id].mode & X_MODE_MASK) { 660 flags = flags | PTE_X; 661 } 662 if (vseg[vseg_id].mode & W_MODE_MASK) { 663 flags = flags | PTE_W; 664 } 665 if (vseg[vseg_id].mode & U_MODE_MASK) { 666 flags = flags | PTE_U; 667 } 568 if (vseg[vseg_id].mode & C_MODE_MASK) flags = flags | PTE_C; 569 if (vseg[vseg_id].mode & X_MODE_MASK) flags = flags | PTE_X; 570 if (vseg[vseg_id].mode & W_MODE_MASK) flags = flags | PTE_W; 571 if (vseg[vseg_id].mode & U_MODE_MASK) flags = flags | PTE_U; 668 572 669 573 #if BOOT_DEBUG_PT … … 674 578 boot_putd(npages); 675 579 boot_puts(" / pbase = "); 676 boot_put x(vseg[vseg_id].pbase);580 boot_putl(vseg[vseg_id].pbase); 677 581 boot_puts("\n"); 678 582 #endif 679 583 // loop on 4K pages 680 for (page_id = 0; page_id < npages; page_id++) { 681 boot_add_pte(vspace_id, vpn, flags, ppn); 584 for (page_id = 0; page_id < npages; page_id++) 585 { 586 boot_add_pte(vspace_id, vpn, flags, ppn, verbose); 682 587 vpn++; 683 588 ppn++; … … 686 591 687 592 // global segments 688 for (vseg_id = 0; vseg_id < header->globals; vseg_id++) { 593 for (vseg_id = 0; vseg_id < header->globals; vseg_id++) 594 { 689 595 vpn = vseg[vseg_id].vbase >> 12; 690 ppn = vseg[vseg_id].pbase >> 12;596 ppn = (unsigned int)(vseg[vseg_id].pbase >> 12); 691 597 npages = vseg[vseg_id].length >> 12; 692 if ((vseg[vseg_id].length & 0xFFF) != 0) { 693 npages++; 694 } 598 if ((vseg[vseg_id].length & 0xFFF) != 0) npages++; 695 599 696 600 flags = PTE_V; 697 if (vseg[vseg_id].mode & C_MODE_MASK) { 698 flags = flags | PTE_C; 699 } 700 if (vseg[vseg_id].mode & X_MODE_MASK) { 701 flags = flags | PTE_X; 702 } 703 if (vseg[vseg_id].mode & W_MODE_MASK) { 704 flags = flags | PTE_W; 705 } 706 if (vseg[vseg_id].mode & U_MODE_MASK) { 707 flags = flags | PTE_U; 708 } 601 if (vseg[vseg_id].mode & C_MODE_MASK) flags = flags | PTE_C; 602 if (vseg[vseg_id].mode & X_MODE_MASK) flags = flags | PTE_X; 603 if (vseg[vseg_id].mode & W_MODE_MASK) flags = flags | PTE_W; 604 if (vseg[vseg_id].mode & U_MODE_MASK) flags = flags | PTE_U; 709 605 710 606 #if BOOT_DEBUG_PT 711 607 boot_puts(vseg[vseg_id].name); 712 boot_puts(" /flags = ");608 boot_puts(" : flags = "); 713 609 boot_putx(flags); 714 610 boot_puts(" / npages = "); 715 611 boot_putd(npages); 716 612 boot_puts(" / pbase = "); 717 boot_put x(vseg[vseg_id].pbase);613 boot_putl(vseg[vseg_id].pbase); 718 614 boot_puts("\n"); 719 615 #endif 720 616 // loop on 4K pages 721 for (page_id = 0; page_id < npages; page_id++) { 722 boot_add_pte(vspace_id, vpn, flags, ppn); 617 for (page_id = 0; page_id < npages; page_id++) 618 { 619 boot_add_pte(vspace_id, vpn, flags, ppn, verbose); 723 620 vpn++; 724 621 ppn++; 725 622 } 726 623 } 727 } 624 } // end boot_vspace_pt_build() 728 625 729 626 730 627 /////////////////////////////////////////////////////////////////////////// 731 // Align the value "toAlign" to the required alignement indicated by732 // alignPow2 ( the logarithme of 2 thealignement).628 // Align the value of paddr or vaddr to the required alignement, 629 // defined by alignPow2 == L2(alignement). 733 630 /////////////////////////////////////////////////////////////////////////// 734 unsigned int align_to(unsigned int toAlign, unsigned int alignPow2) { 631 paddr_t paddr_align_to(paddr_t paddr, unsigned int alignPow2) 632 { 633 paddr_t mask = (1 << alignPow2) - 1; 634 return ((paddr + mask) & ~mask); 635 } 636 637 unsigned int vaddr_align_to(unsigned int vaddr, unsigned int alignPow2) 638 { 735 639 unsigned int mask = (1 << alignPow2) - 1; 736 return ((toAlign + mask) & ~mask); 737 } 738 640 return ((vaddr + mask) & ~mask); 641 } 739 642 740 643 /////////////////////////////////////////////////////////////////////////// 741 // This function compute the physical base address for a vseg644 // This function computes the physical base address for a vseg 742 645 // as specified in the mapping info data structure. 743 646 // It updates the pbase and the length fields of the vseg. … … 747 650 // It is a global vseg if vspace_id = (-1). 748 651 /////////////////////////////////////////////////////////////////////////// 749 void boot_vseg_map(mapping_vseg_t * vseg, unsigned int vspace_id) { 652 void boot_vseg_map(mapping_vseg_t * vseg, unsigned int vspace_id) 653 { 750 654 unsigned int vobj_id; 751 655 unsigned int cur_vaddr; 752 unsigned int cur_paddr; 656 paddr_t cur_paddr; 657 unsigned int offset; 658 753 659 mapping_header_t * header = (mapping_header_t *) & seg_mapping_base; 754 mapping_vobj_t * vobj= boot_get_vobj_base(header);660 mapping_vobj_t * vobj = boot_get_vobj_base(header); 755 661 756 662 // get physical segment pointer 757 mapping_pseg_t 663 mapping_pseg_t* pseg = boot_pseg_get(vseg->psegid); 758 664 759 665 // compute vseg physical base address 760 if (vseg->ident != 0) { // identity mapping required 666 if (vseg->ident != 0) // identity mapping required 667 { 761 668 vseg->pbase = vseg->vbase; 762 669 } 763 else { // unconstrained mapping 670 else // unconstrained mapping 671 { 764 672 vseg->pbase = pseg->next_base; 765 673 766 674 // test alignment constraint 767 if (vobj[vseg->vobj_offset].align) { 768 vseg->pbase = align_to(vseg->pbase, vobj[vseg->vobj_offset].align); 675 if (vobj[vseg->vobj_offset].align) 676 { 677 vseg->pbase = paddr_align_to(vseg->pbase, vobj[vseg->vobj_offset].align); 769 678 } 770 679 } … … 778 687 cur_paddr = vseg->pbase; 779 688 780 for (vobj_id = vseg->vobj_offset; vobj_id < (vseg->vobj_offset + vseg->vobjs); vobj_id++) { 781 if (vobj[vobj_id].align) { 782 cur_paddr = align_to(cur_paddr, vobj[vobj_id].align); 783 cur_vaddr = align_to(cur_vaddr, vobj[vobj_id].align); 689 for (vobj_id = vseg->vobj_offset; 690 vobj_id < (vseg->vobj_offset + vseg->vobjs); vobj_id++) 691 { 692 if (vobj[vobj_id].align) 693 { 694 cur_paddr = paddr_align_to(cur_paddr, vobj[vobj_id].align); 695 cur_vaddr = vaddr_align_to(cur_vaddr, vobj[vobj_id].align); 784 696 } 785 697 // set vaddr/paddr for current vobj … … 787 699 vobj[vobj_id].paddr = cur_paddr; 788 700 789 // initialise boot_ptabs_vaddr[] if current vobj is a PTAB 790 if (vobj[vobj_id].type == VOBJ_TYPE_PTAB) { 791 if (vspace_id == ((unsigned int) -1)) { // global vseg 701 // initialise boot_ptabs_vaddr[] & boot_ptabs-paddr[] if PTAB 702 if (vobj[vobj_id].type == VOBJ_TYPE_PTAB) 703 { 704 if (vspace_id == ((unsigned int) -1)) // global vseg 705 { 792 706 boot_puts("\n[BOOT ERROR] in boot_vseg_map() function: "); 793 707 boot_puts("a PTAB vobj cannot be global"); 794 708 boot_exit(); 795 709 } 796 // we need at least one PT2 => ( boot_max_pt2[vspace_id] >= 1) 797 if (vobj[vobj_id].length < (PT1_SIZE + PT2_SIZE)) { 710 // we need at least one PT2 711 if (vobj[vobj_id].length < (PT1_SIZE + PT2_SIZE)) 712 { 798 713 boot_puts("\n[BOOT ERROR] in boot_vseg_map() function, "); 799 714 boot_puts("PTAB too small, minumum size is: "); … … 802 717 } 803 718 // register both physical and virtual page table address 804 boot_ptabs_vaddr[vspace_id] = (page_table_t *) vobj[vobj_id].vaddr; 805 boot_ptabs_paddr[vspace_id] = (page_table_t *) vobj[vobj_id].paddr; 806 807 /* computing the number of second level page */ 719 boot_ptabs_vaddr[vspace_id] = vobj[vobj_id].vaddr; 720 boot_ptabs_paddr[vspace_id] = vobj[vobj_id].paddr; 721 722 // reset all valid bits in PT1 723 for ( offset = 0 ; offset < 8192 ; offset = offset + 4) 724 { 725 boot_physical_write( cur_paddr + offset, 0); 726 } 727 728 // computing the number of second level pages 808 729 boot_max_pt2[vspace_id] = (vobj[vobj_id].length - PT1_SIZE) / PT2_SIZE; 809 730 } 731 810 732 // set next vaddr/paddr 811 cur_vaddr += vobj[vobj_id].length; 812 cur_paddr += vobj[vobj_id].length; 813 733 cur_vaddr = cur_vaddr + vobj[vobj_id].length; 734 cur_paddr = cur_paddr + vobj[vobj_id].length; 814 735 } // end for vobjs 815 736 816 737 //set the vseg length 817 vseg->length = align_to((cur_paddr - vseg->pbase), 12);738 vseg->length = vaddr_align_to((unsigned int)(cur_paddr - vseg->pbase), 12); 818 739 819 740 // checking pseg overflow 820 741 if ((vseg->pbase < pseg->base) || 821 ((vseg->pbase + vseg->length) > (pseg->base + pseg->length))) { 742 ((vseg->pbase + vseg->length) > (pseg->base + pseg->length))) 743 { 822 744 boot_puts("\n[BOOT ERROR] in boot_vseg_map() function\n"); 823 745 boot_puts("impossible mapping for virtual segment: "); … … 825 747 boot_puts("\n"); 826 748 boot_puts("vseg pbase = "); 827 boot_put x(vseg->pbase);749 boot_putl(vseg->pbase); 828 750 boot_puts("\n"); 829 751 boot_puts("vseg length = "); … … 831 753 boot_puts("\n"); 832 754 boot_puts("pseg pbase = "); 833 boot_put x(pseg->base);755 boot_putl(pseg->base); 834 756 boot_puts("\n"); 835 757 boot_puts("pseg length = "); 836 boot_put x(pseg->length);758 boot_putl(pseg->length); 837 759 boot_puts("\n"); 838 760 boot_exit(); … … 846 768 boot_putx(vseg->vbase); 847 769 boot_puts(" / pbase = "); 848 boot_put x(vseg->pbase);770 boot_putl(vseg->pbase); 849 771 boot_puts("\n"); 850 772 #endif 851 773 852 // set the next_base field in vseg 853 if (vseg->ident == 0 && pseg->type != PSEG_TYPE_PERI) { 774 // set the next_base field in pseg when it's a RAM 775 if ( pseg->type == PSEG_TYPE_RAM ) 776 { 854 777 pseg->next_base = vseg->pbase + vseg->length; 855 778 } 856 857 } // end boot_vseg_map() 779 } // end boot_vseg_map() 858 780 859 781 ///////////////////////////////////////////////////////////////////// … … 861 783 // structure (soft), and the giet_config file (hard). 862 784 ///////////////////////////////////////////////////////////////////// 863 void boot_check_mapping() { 785 void boot_check_mapping() 786 { 864 787 mapping_header_t * header = (mapping_header_t *) & seg_mapping_base; 865 788 mapping_cluster_t * cluster = boot_get_cluster_base(header); … … 867 790 868 791 // checking mapping availability 869 if (header->signature != IN_MAPPING_SIGNATURE) { 792 if (header->signature != IN_MAPPING_SIGNATURE) 793 { 870 794 boot_puts("\n[BOOT ERROR] Illegal mapping signature: "); 871 795 boot_putx(header->signature); … … 874 798 } 875 799 // checking number of clusters 876 if (header->clusters != NB_CLUSTERS) { 800 if (header->clusters != NB_CLUSTERS) 801 { 877 802 boot_puts("\n[BOOT ERROR] Incoherent NB_CLUSTERS"); 878 803 boot_puts("\n - In giet_config, value = "); … … 884 809 } 885 810 // checking number of virtual spaces 886 if (header->vspaces > GIET_NB_VSPACE_MAX) { 811 if (header->vspaces > GIET_NB_VSPACE_MAX) 812 { 887 813 boot_puts("\n[BOOT ERROR] : number of vspaces > GIET_NB_VSPACE_MAX\n"); 888 814 boot_puts("\n"); … … 894 820 unsigned int tty_found = 0; 895 821 unsigned int nic_found = 0; 896 for (cluster_id = 0; cluster_id < NB_CLUSTERS; cluster_id++) { 822 for (cluster_id = 0; cluster_id < NB_CLUSTERS; cluster_id++) 823 { 897 824 // NB_PROCS_MAX 898 if (cluster[cluster_id].procs > NB_PROCS_MAX) { 825 if (cluster[cluster_id].procs > NB_PROCS_MAX) 826 { 899 827 boot_puts("\n[BOOT ERROR] too many processors in cluster "); 900 828 boot_putd(cluster_id); … … 907 835 for (periph_id = cluster[cluster_id].periph_offset; 908 836 periph_id < cluster[cluster_id].periph_offset + cluster[cluster_id].periphs; 909 periph_id++) { 910 // NB_TTYS 911 if (periph[periph_id].type == PERIPH_TYPE_TTY) { 912 if (tty_found) { 837 periph_id++) 838 { 839 // NB_TTY_CHANNELS 840 if (periph[periph_id].type == PERIPH_TYPE_TTY) 841 { 842 if (tty_found) 843 { 913 844 boot_puts("\n[BOOT ERROR] TTY component should not be replicated\n"); 914 845 boot_exit(); 915 846 } 916 if (periph[periph_id].channels > NB_TTYS) { 917 boot_puts("\n[BOOT ERROR] Wrong NB_TTYS in cluster "); 847 if (periph[periph_id].channels > NB_TTY_CHANNELS) 848 { 849 boot_puts("\n[BOOT ERROR] Wrong NB_TTY_CHANNELS in cluster "); 918 850 boot_putd(cluster_id); 919 851 boot_puts(" : ttys = "); … … 924 856 tty_found = 1; 925 857 } 926 // NB_NICS 927 if (periph[periph_id].type == PERIPH_TYPE_NIC) { 928 if (nic_found) { 858 // NB_NIC_CHANNELS 859 if (periph[periph_id].type == PERIPH_TYPE_NIC) 860 { 861 if (nic_found) 862 { 929 863 boot_puts("\n[BOOT ERROR] NIC component should not be replicated\n"); 930 864 boot_exit(); 931 865 } 932 if (periph[periph_id].channels != NB_NICS) { 933 boot_puts("\n[BOOT ERROR] Wrong NB_NICS in cluster "); 866 if (periph[periph_id].channels != NB_NIC_CHANNELS) 867 { 868 boot_puts("\n[BOOT ERROR] Wrong NB_NIC_CHANNELS in cluster "); 934 869 boot_putd(cluster_id); 935 870 boot_puts(" : nics = "); … … 941 876 } 942 877 // NB_TIMERS 943 if (periph[periph_id].type == PERIPH_TYPE_TIM) { 944 if (periph[periph_id].channels > NB_TIMERS_MAX) { 878 if (periph[periph_id].type == PERIPH_TYPE_TIM) 879 { 880 if (periph[periph_id].channels > NB_TIM_CHANNELS) 881 { 945 882 boot_puts("\n[BOOT ERROR] Too much user timers in cluster "); 946 883 boot_putd(cluster_id); … … 952 889 } 953 890 // NB_DMAS 954 if (periph[periph_id].type == PERIPH_TYPE_DMA) { 955 if (periph[periph_id].channels != NB_DMAS_MAX) { 891 if (periph[periph_id].type == PERIPH_TYPE_DMA) 892 { 893 if (periph[periph_id].channels != NB_DMA_CHANNELS) 894 { 956 895 boot_puts("\n[BOOT ERROR] Too much DMA channels in cluster "); 957 896 boot_putd(cluster_id); 958 897 boot_puts(" : channels = "); 959 898 boot_putd(periph[periph_id].channels); 960 boot_puts(" - NB_DMA S_MAX: ");961 boot_putd(NB_DMA S_MAX);899 boot_puts(" - NB_DMA_CHANNELS : "); 900 boot_putd(NB_DMA_CHANNELS); 962 901 boot_puts("\n"); 963 902 boot_exit(); … … 968 907 } // end boot_check_mapping() 969 908 970 971 909 ///////////////////////////////////////////////////////////////////// 972 910 // This function initialises the physical pages table allocators 973 911 // for all psegs (i.e. next_base field of the pseg). 974 // In each cluster containing processors, it reserve space for the975 // schedulers in the first RAM pseg found (4k bytes per processor).976 912 ///////////////////////////////////////////////////////////////////// 977 void boot_psegs_init() {978 mapping_header_t * header = (mapping_header_t *) &seg_mapping_base; 979 980 mapping_cluster_t 981 mapping_pseg_t * pseg= boot_get_pseg_base(header);913 void boot_psegs_init() 914 { 915 mapping_header_t* header = (mapping_header_t *) &seg_mapping_base; 916 mapping_cluster_t* cluster = boot_get_cluster_base(header); 917 mapping_pseg_t* pseg = boot_get_pseg_base(header); 982 918 983 919 unsigned int cluster_id; 984 920 unsigned int pseg_id; 985 unsigned int found;986 921 987 922 #if BOOT_DEBUG_PT 988 boot_puts 989 ("\n[BOOT DEBUG] ****** psegs allocators nitialisation ******\n"); 990 #endif 991 992 for (cluster_id = 0; cluster_id < header->clusters; cluster_id++) { 993 if (cluster[cluster_id].procs > NB_PROCS_MAX) { 923 boot_puts ("\n[BOOT DEBUG] ****** psegs allocators initialisation ******\n"); 924 #endif 925 926 for (cluster_id = 0; cluster_id < header->clusters; cluster_id++) 927 { 928 if (cluster[cluster_id].procs > NB_PROCS_MAX) 929 { 994 930 boot_puts("\n[BOOT ERROR] The number of processors in cluster "); 995 931 boot_putd(cluster_id); … … 998 934 } 999 935 1000 found = 0;1001 1002 936 for (pseg_id = cluster[cluster_id].pseg_offset; 1003 937 pseg_id < cluster[cluster_id].pseg_offset + cluster[cluster_id].psegs; 1004 pseg_id++) { 1005 unsigned int free = pseg[pseg_id].base; 1006 1007 if ((pseg[pseg_id].type == PSEG_TYPE_RAM) && (found == 0)) { 1008 free = free + (cluster[cluster_id].procs << 12); 1009 found = 1; 1010 } 1011 pseg[pseg_id].next_base = free; 938 pseg_id++) 939 { 940 pseg[pseg_id].next_base = pseg[pseg_id].base; 1012 941 1013 942 #if BOOT_DEBUG_PT 1014 1015 1016 1017 1018 1019 boot_putx(pseg[pseg_id].next_base);1020 943 boot_puts("cluster "); 944 boot_putd(cluster_id); 945 boot_puts(" / pseg "); 946 boot_puts(pseg[pseg_id].name); 947 boot_puts(" : next_base = "); 948 boot_putl(pseg[pseg_id].next_base); 949 boot_puts("\n"); 1021 950 #endif 1022 951 } 1023 952 } 1024 953 } // end boot_psegs_init() 1025 1026 954 1027 955 ///////////////////////////////////////////////////////////////////// 1028 956 // This function builds the page tables for all virtual spaces 1029 // defined in the mapping_info data structure. 1030 // For each virtual space, it maps both the global vsegs 1031 // (replicated in all vspaces), and the private vsegs. 957 // defined in the mapping_info data structure, in three steps: 958 // - step 1 : It computes the physical base address for global vsegs 959 // and for all associated vobjs. 960 // - step 2 : It computes the physical base address for all private 961 // vsegs and all vobjs in each virtual space. 962 // - step 3 : It actually fill the page table for each vspace. 1032 963 ///////////////////////////////////////////////////////////////////// 1033 void boot_pt_init() { 964 void boot_pt_init() 965 { 1034 966 mapping_header_t * header = (mapping_header_t *) &seg_mapping_base; 1035 1036 967 mapping_vspace_t * vspace = boot_get_vspace_base(header); 1037 mapping_vseg_t * vseg= boot_get_vseg_base(header);968 mapping_vseg_t * vseg = boot_get_vseg_base(header); 1038 969 1039 970 unsigned int vspace_id; … … 1041 972 1042 973 #if BOOT_DEBUG_PT 1043 boot_puts("\n[BOOT DEBUG] ****** mapping global vsegs ******\n"); 1044 #endif 1045 1046 // step 1 : first loop on virtual spaces to map global vsegs 1047 for (vseg_id = 0; vseg_id < header->globals; vseg_id++) { 974 boot_puts("\n[BOOT DEBUG] ****** mapping global vsegs ******\n"); 975 #endif 976 977 // step 1 : loop on virtual spaces to map global vsegs 978 for (vseg_id = 0; vseg_id < header->globals; vseg_id++) 979 { 1048 980 boot_vseg_map(&vseg[vseg_id], ((unsigned int) (-1))); 1049 981 } 1050 982 1051 983 // step 2 : loop on virtual vspaces to map private vsegs 1052 for (vspace_id = 0; vspace_id < header->vspaces; vspace_id++) { 984 for (vspace_id = 0; vspace_id < header->vspaces; vspace_id++) 985 { 1053 986 1054 987 #if BOOT_DEBUG_PT 1055 1056 1057 988 boot_puts("\n[BOOT DEBUG] ****** mapping private vsegs in vspace "); 989 boot_puts(vspace[vspace_id].name); 990 boot_puts(" ******\n"); 1058 991 #endif 1059 992 1060 993 for (vseg_id = vspace[vspace_id].vseg_offset; 1061 994 vseg_id < (vspace[vspace_id].vseg_offset + vspace[vspace_id].vsegs); 1062 vseg_id++) { 995 vseg_id++) 996 { 1063 997 boot_vseg_map(&vseg[vseg_id], vspace_id); 1064 998 } … … 1066 1000 1067 1001 // step 3 : loop on the vspaces to build the page tables 1068 for (vspace_id = 0; vspace_id < header->vspaces; vspace_id++) {1069 1002 for (vspace_id = 0; vspace_id < header->vspaces; vspace_id++) 1003 { 1070 1004 #if BOOT_DEBUG_PT 1071 boot_puts("\n[BOOT DEBUG] ****** building page table for vspace "); 1072 boot_puts(vspace[vspace_id].name); 1073 boot_puts(" ******\n"); 1074 #endif 1075 1005 boot_puts("\n[BOOT DEBUG] ****** building page table for vspace "); 1006 boot_puts(vspace[vspace_id].name); 1007 boot_puts(" ******\n"); 1008 #endif 1076 1009 boot_vspace_pt_build(vspace_id); 1077 1010 1078 1011 #if BOOT_DEBUG_PT 1079 1080 boot_putx((unsigned int)boot_ptabs_paddr[vspace_id]);1081 boot_puts(", page tablenumber of PT2 = ");1082 1083 1012 boot_puts("\n>>> page table physical address = "); 1013 boot_putl(boot_ptabs_paddr[vspace_id]); 1014 boot_puts(", number of PT2 = "); 1015 boot_putd((unsigned int) boot_max_pt2[vspace_id]); 1016 boot_puts("\n"); 1084 1017 #endif 1085 1018 } 1086 1019 } // end boot_pt_init() 1087 1088 1020 1089 1021 /////////////////////////////////////////////////////////////////////////////// … … 1091 1023 // such as mwmr channels, barriers and locks, because these vobjs 1092 1024 // are not known, and not initialized by the compiler. 1025 // Warning : The MMU is supposed to be activated... 1093 1026 /////////////////////////////////////////////////////////////////////////////// 1094 void boot_vobjs_init() { 1095 mapping_header_t * header = (mapping_header_t *) & seg_mapping_base; 1096 mapping_vspace_t * vspace = boot_get_vspace_base(header); 1097 mapping_vobj_t * vobj = boot_get_vobj_base(header); 1027 void boot_vobjs_init() 1028 { 1029 mapping_header_t* header = (mapping_header_t *) & seg_mapping_base; 1030 mapping_vspace_t* vspace = boot_get_vspace_base(header); 1031 mapping_vobj_t* vobj = boot_get_vobj_base(header); 1098 1032 1099 1033 unsigned int vspace_id; 1100 1034 unsigned int vobj_id; 1101 1035 1102 // loop on the vspaces 1103 for (vspace_id = 0; vspace_id < header->vspaces; vspace_id++) { 1036 // loop on the vspaces 1037 for (vspace_id = 0; vspace_id < header->vspaces; vspace_id++) 1038 { 1104 1039 1105 1040 #if BOOT_DEBUG_VOBJS 1106 1107 1108 1041 boot_puts("\n[BOOT DEBUG] ****** vobjs initialisation in vspace "); 1042 boot_puts(vspace[vspace_id].name); 1043 boot_puts(" ******\n"); 1109 1044 #endif 1110 1045 … … 1113 1048 // loop on the vobjs 1114 1049 for (vobj_id = vspace[vspace_id].vobj_offset; 1115 vobj_id < (vspace[vspace_id].vobj_offset + vspace[vspace_id].vobjs); 1116 vobj_id++) { 1117 switch (vobj[vobj_id].type) { 1050 vobj_id < (vspace[vspace_id].vobj_offset + vspace[vspace_id].vobjs); 1051 vobj_id++) 1052 { 1053 switch (vobj[vobj_id].type) 1054 { 1118 1055 case VOBJ_TYPE_MWMR: // storage capacity is (vobj.length/4 - 5) words 1119 1056 { 1120 mwmr_channel_t * mwmr = (mwmr_channel_t *) (vobj[vobj_id].paddr);1057 mwmr_channel_t* mwmr = (mwmr_channel_t *) (vobj[vobj_id].vaddr); 1121 1058 mwmr->ptw = 0; 1122 1059 mwmr->ptr = 0; … … 1126 1063 mwmr->lock = 0; 1127 1064 #if BOOT_DEBUG_VOBJS 1128 1129 1130 1131 1132 1133 1134 1065 boot_puts("MWMR : "); 1066 boot_puts(vobj[vobj_id].name); 1067 boot_puts(" / depth = "); 1068 boot_putd(mwmr->depth); 1069 boot_puts(" / width = "); 1070 boot_putd(mwmr->width); 1071 boot_puts("\n"); 1135 1072 #endif 1136 1073 break; … … 1139 1076 { 1140 1077 #if BOOT_DEBUG_VOBJS 1141 1142 1143 1144 1145 1078 boot_puts("ELF : "); 1079 boot_puts(vobj[vobj_id].name); 1080 boot_puts(" / length = "); 1081 boot_putx(vobj[vobj_id].length); 1082 boot_puts("\n"); 1146 1083 #endif 1147 1084 break; … … 1150 1087 { 1151 1088 #if BOOT_DEBUG_VOBJS 1152 1153 1154 1155 1156 1089 boot_puts("BLOB : "); 1090 boot_puts(vobj[vobj_id].name); 1091 boot_puts(" / length = "); 1092 boot_putx(vobj[vobj_id].length); 1093 boot_puts("\n"); 1157 1094 #endif 1158 1095 break; … … 1160 1097 case VOBJ_TYPE_BARRIER: // init is the number of participants 1161 1098 { 1162 giet_barrier_t * barrier = (giet_barrier_t *) (vobj[vobj_id].paddr);1099 giet_barrier_t* barrier = (giet_barrier_t *) (vobj[vobj_id].vaddr); 1163 1100 barrier->count = vobj[vobj_id].init; 1164 1101 barrier->init = vobj[vobj_id].init; 1165 1102 #if BOOT_DEBUG_VOBJS 1166 1167 1168 1169 1170 1103 boot_puts("BARRIER : "); 1104 boot_puts(vobj[vobj_id].name); 1105 boot_puts(" / init_value = "); 1106 boot_putd(barrier->init); 1107 boot_puts("\n"); 1171 1108 #endif 1172 1109 break; 1173 1110 } 1174 case VOBJ_TYPE_LOCK: // init is "not taken"1175 { 1176 unsigned int * lock = (unsigned int *) (vobj[vobj_id].paddr);1111 case VOBJ_TYPE_LOCK: // init value is "not taken" 1112 { 1113 unsigned int* lock = (unsigned int *) (vobj[vobj_id].vaddr); 1177 1114 *lock = 0; 1178 1115 #if BOOT_DEBUG_VOBJS 1179 1180 1181 1116 boot_puts("LOCK : "); 1117 boot_puts(vobj[vobj_id].name); 1118 boot_puts("\n"); 1182 1119 #endif 1183 1120 break; … … 1186 1123 { 1187 1124 #if BOOT_DEBUG_VOBJS 1188 1189 1190 1191 1192 1193 1194 1125 boot_puts("BUFFER : "); 1126 boot_puts(vobj[vobj_id].name); 1127 boot_puts(" / paddr = "); 1128 boot_putx(vobj[vobj_id].paddr); 1129 boot_puts(" / length = "); 1130 boot_putx(vobj[vobj_id].length); 1131 boot_puts("\n"); 1195 1132 #endif 1196 1133 break; … … 1198 1135 case VOBJ_TYPE_MEMSPACE: 1199 1136 { 1200 giet_memspace_t * memspace = (giet_memspace_t *) vobj[vobj_id].paddr;1137 giet_memspace_t* memspace = (giet_memspace_t *) vobj[vobj_id].vaddr; 1201 1138 memspace->buffer = (void *) vobj[vobj_id].vaddr + 8; 1202 1139 memspace->size = vobj[vobj_id].length - 8; 1203 1140 #if BOOT_DEBUG_VOBJS 1204 boot_puts("MEMSPACE : "); 1205 boot_puts(vobj[vobj_id].name); 1206 boot_puts(" / paddr = "); 1207 boot_putx(vobj[vobj_id].paddr); 1208 boot_puts(" / vaddr = "); 1209 boot_putx(vobj[vobj_id].vaddr); 1210 boot_puts(" / length = "); 1211 boot_putx(vobj[vobj_id].length); 1212 boot_puts(" / buffer = "); 1213 boot_putx(memspace->buffer); 1214 boot_puts(" / size = "); 1215 boot_putx(memspace->size); 1216 boot_puts("\n"); 1141 boot_puts("MEMSPACE : "); 1142 boot_puts(vobj[vobj_id].name); 1143 boot_puts(" / vaddr = "); 1144 boot_putx(vobj[vobj_id].vaddr); 1145 boot_puts(" / length = "); 1146 boot_putx(vobj[vobj_id].length); 1147 boot_puts(" / buffer = "); 1148 boot_putx((unsigned int)memspace->buffer); 1149 boot_puts(" / size = "); 1150 boot_putx(memspace->size); 1151 boot_puts("\n"); 1217 1152 #endif 1218 1153 break; … … 1222 1157 ptab_found = 1; 1223 1158 #if BOOT_DEBUG_VOBJS 1224 1225 1226 1227 1228 1159 boot_puts("PTAB : "); 1160 boot_puts(vobj[vobj_id].name); 1161 boot_puts(" / length = "); 1162 boot_putx(vobj[vobj_id].length); 1163 boot_puts("\n"); 1229 1164 #endif 1230 1165 break; … … 1232 1167 case VOBJ_TYPE_CONST: 1233 1168 { 1234 unsigned int *addr = (unsigned int *) vobj[vobj_id].paddr;1169 unsigned int* addr = (unsigned int *) vobj[vobj_id].vaddr; 1235 1170 *addr = vobj[vobj_id].init; 1236 1171 #if BOOT_DEBUG_VOBJS 1237 1238 1239 1240 1241 1242 1243 1172 boot_puts("CONST : "); 1173 boot_puts(vobj[vobj_id].name); 1174 boot_puts(" / Paddr :"); 1175 boot_putx(vobj[vobj_id].paddr); 1176 boot_puts(" / init = "); 1177 boot_putx(*addr); 1178 boot_puts("\n"); 1244 1179 #endif 1245 1180 break; … … 1247 1182 default: 1248 1183 { 1249 boot_puts("\n[ INIT ERROR] illegal vobj type: ");1184 boot_puts("\n[BOOT ERROR] illegal vobj type: "); 1250 1185 boot_putd(vobj[vobj_id].type); 1251 1186 boot_puts("\n"); … … 1254 1189 } // end switch type 1255 1190 } // end loop on vobjs 1256 if (ptab_found == 0) { 1257 boot_puts("\n[INIT ERROR] Missing PTAB for vspace "); 1191 if (ptab_found == 0) 1192 { 1193 boot_puts("\n[BOOT ERROR] Missing PTAB for vspace "); 1258 1194 boot_putd(vspace_id); 1259 1195 boot_exit(); … … 1262 1198 } // end boot_vobjs_init() 1263 1199 1264 1265 void mwmr_hw_init(void * coproc, enum mwmrPortDirection way, 1266 unsigned int no, const mwmr_channel_t * pmwmr) { 1267 volatile unsigned int *cbase = (unsigned int *) coproc; 1268 1269 cbase[MWMR_CONFIG_FIFO_WAY] = way; 1270 cbase[MWMR_CONFIG_FIFO_NO] = no; 1271 cbase[MWMR_CONFIG_STATUS_ADDR] = (unsigned int) pmwmr; 1272 cbase[MWMR_CONFIG_WIDTH] = pmwmr->width; 1273 cbase[MWMR_CONFIG_DEPTH] = pmwmr->depth; 1274 cbase[MWMR_CONFIG_BUFFER_ADDR] = (unsigned int) &pmwmr->data; 1275 cbase[MWMR_CONFIG_RUNNING] = 1; 1276 } 1277 1200 //////////////////////////////////////////////////////////////////////////////// 1201 // This function initializes one MWMR controller channel. 1202 // - coproc_pbase : physical base address of the Coproc configuration segment 1203 // - channel_pbase : physical base address of the MWMR channel segment 1204 // Warning : the channel physical base address should be on 32 bits, as the 1205 // MWMR controller configuration registers are 32 bits. 1206 // TODO : Introduce a MWMR_CONFIG_PADDR_EXT register in the MWMR coprocessor 1207 // To support addresses > 32 bits and remove this limitation... 1208 /////////////////////////////////////////////////////////////////////////////// 1209 void mwmr_hw_init(paddr_t coproc_pbase, 1210 enum mwmrPortDirection way, 1211 unsigned int no, 1212 paddr_t channel_pbase) 1213 { 1214 if ( (channel_pbase>>32) != 0 ) 1215 { 1216 boot_puts("\n[BOOT ERROR] MWMR controller does not support address > 32 bits\n"); 1217 boot_exit(); 1218 } 1219 1220 unsigned int lsb = (unsigned int)channel_pbase; 1221 // unsigned int msb = (unsigned int)(channel_pbase>>32); 1222 1223 unsigned int depth = boot_physical_read( channel_pbase + 16 ); 1224 unsigned int width = boot_physical_read( channel_pbase + 20 ); 1225 1226 boot_physical_write( coproc_pbase + MWMR_CONFIG_FIFO_WAY*4, way ); 1227 boot_physical_write( coproc_pbase + MWMR_CONFIG_FIFO_NO*4, no ); 1228 boot_physical_write( coproc_pbase + MWMR_CONFIG_WIDTH*4, width); 1229 boot_physical_write( coproc_pbase + MWMR_CONFIG_DEPTH*4, depth); 1230 boot_physical_write( coproc_pbase + MWMR_CONFIG_STATUS_ADDR*4, lsb); 1231 boot_physical_write( coproc_pbase + MWMR_CONFIG_BUFFER_ADDR*4, lsb + 24 ); 1232 // boot_physical_write( coproc_pbase + MWMR_CONFIG_PADDR_EXT*4, msb); 1233 boot_physical_write( coproc_pbase + MWMR_CONFIG_RUNNING*4, 1 ); 1234 } 1278 1235 1279 1236 //////////////////////////////////////////////////////////////////////////////// … … 1281 1238 // in the mapping_info file. 1282 1239 //////////////////////////////////////////////////////////////////////////////// 1283 void boot_peripherals_init() { 1240 void boot_peripherals_init() 1241 { 1284 1242 mapping_header_t * header = (mapping_header_t *) & seg_mapping_base; 1285 1243 mapping_cluster_t * cluster = boot_get_cluster_base(header); … … 1297 1255 unsigned int channel_id; 1298 1256 1299 for (cluster_id = 0; cluster_id < header->clusters; cluster_id++) { 1257 for (cluster_id = 0; cluster_id < header->clusters; cluster_id++) 1258 { 1300 1259 1301 1260 #if BOOT_DEBUG_PERI 1302 boot_puts 1303 ("\n[BOOT DEBUG] ****** peripheral initialisation in cluster "); 1304 boot_putd(cluster_id); 1305 boot_puts(" ******\n"); 1261 boot_puts("\n[BOOT DEBUG] ****** peripherals initialisation in cluster "); 1262 boot_putd(cluster_id); 1263 boot_puts(" ******\n"); 1306 1264 #endif 1307 1265 1308 1266 for (periph_id = cluster[cluster_id].periph_offset; 1309 periph_id < cluster[cluster_id].periph_offset + 1310 cluster[cluster_id].periphs; periph_id++) { 1267 periph_id < cluster[cluster_id].periph_offset + 1268 cluster[cluster_id].periphs; periph_id++) 1269 { 1311 1270 unsigned int type = periph[periph_id].type; 1312 1271 unsigned int channels = periph[periph_id].channels; 1313 1272 unsigned int pseg_id = periph[periph_id].psegid; 1314 1273 1315 unsigned int * pseg_base = (unsigned int *)pseg[pseg_id].base;1274 paddr_t pbase = pseg[pseg_id].base; 1316 1275 1317 1276 #if BOOT_DEBUG_PERI 1318 boot_puts("- peripheral type : "); 1319 boot_putd(type); 1320 boot_puts(" / address = "); 1321 boot_putx((unsigned int) pseg_base); 1322 boot_puts(" / channels = "); 1323 boot_putd(channels); 1324 boot_puts("\n"); 1325 #endif 1326 1327 switch (type) { 1277 boot_puts("- peripheral type : "); 1278 boot_putd(type); 1279 boot_puts(" / pbase = "); 1280 boot_putl(pbase); 1281 boot_puts(" / channels = "); 1282 boot_putd(channels); 1283 boot_puts("\n"); 1284 #endif 1285 1286 switch (type) 1287 { 1328 1288 case PERIPH_TYPE_IOC: // vci_block_device component 1329 pseg_base[BLOCK_DEVICE_IRQ_ENABLE] = 1; 1289 { 1290 paddr_t paddr = pbase + BLOCK_DEVICE_IRQ_ENABLE*4; 1291 boot_physical_write(paddr, 1); 1330 1292 #if BOOT_DEBUG_PERI 1331 1332 #endif 1333 break;1334 1293 boot_puts("- IOC initialised\n"); 1294 #endif 1295 } 1296 break; 1335 1297 case PERIPH_TYPE_DMA: // vci_multi_dma component 1336 for (channel_id = 0; channel_id < channels; channel_id++) { 1337 pseg_base[DMA_IRQ_DISABLE + channel_id * DMA_SPAN] = 0; 1298 for (channel_id = 0; channel_id < channels; channel_id++) 1299 { 1300 paddr_t paddr = pbase + (channel_id*DMA_SPAN + DMA_IRQ_DISABLE) * 4; 1301 boot_physical_write(paddr, 0); 1338 1302 } 1339 1303 #if BOOT_DEBUG_PERI 1340 boot_puts("- DMA initialised\n"); 1341 #endif 1342 break; 1343 1304 boot_puts("- DMA initialised\n"); 1305 #endif 1306 break; 1344 1307 case PERIPH_TYPE_NIC: // vci_multi_nic component 1345 for (channel_id = 0; channel_id < channels; channel_id++) { 1308 for (channel_id = 0; channel_id < channels; channel_id++) 1309 { 1346 1310 // TODO 1347 1311 } 1348 1312 #if BOOT_DEBUG_PERI 1349 boot_puts("- NIC initialised\n"); 1350 #endif 1351 break; 1352 1313 boot_puts("- NIC initialised\n"); 1314 #endif 1315 break; 1353 1316 case PERIPH_TYPE_TTY: // vci_multi_tty component 1354 1317 #if BOOT_DEBUG_PERI 1355 boot_puts("- TTY initialised\n"); 1356 #endif 1357 break; 1358 1318 boot_puts("- TTY initialised\n"); 1319 #endif 1320 break; 1359 1321 case PERIPH_TYPE_IOB: // vci_io_bridge component 1360 if (IOMMU_ACTIVE) { 1322 if (IOMMU_ACTIVE) 1323 { 1361 1324 // TODO 1362 1325 // get the iommu page table physical address … … 1368 1331 } 1369 1332 #if BOOT_DEBUG_PERI 1370 1371 #endif 1372 1373 } 1374 } 1333 boot_puts("- IOB initialised\n"); 1334 #endif 1335 break; 1336 } // end switch periph type 1337 } // end for periphs 1375 1338 1376 1339 #if BOOT_DEBUG_PERI 1377 boot_puts 1378 ("\n[BOOT DEBUG] ****** coprocessors initialisation in cluster "); 1379 boot_putd(cluster_id); 1380 boot_puts(" ******\n"); 1340 boot_puts("\n[BOOT DEBUG] ****** coprocessors initialisation in cluster "); 1341 boot_putd(cluster_id); 1342 boot_puts(" ******\n"); 1381 1343 #endif 1382 1344 1383 1345 for (coproc_id = cluster[cluster_id].coproc_offset; 1384 coproc_id < cluster[cluster_id].coproc_offset + 1385 cluster[cluster_id].coprocs; coproc_id++) { 1386 unsigned no_fifo_to = 0; //FIXME: should it be the map.xml who define the order? 1346 coproc_id < cluster[cluster_id].coproc_offset + 1347 cluster[cluster_id].coprocs; coproc_id++) 1348 { 1349 unsigned no_fifo_to = 0; //FIXME: should the map.xml define the order? 1387 1350 unsigned no_fifo_from = 0; 1388 unsigned int cpseg = pseg[coproc[coproc_id].psegid].base; 1351 1352 // Get physical base address for MWMR controler 1353 paddr_t coproc_pbase = pseg[coproc[coproc_id].psegid].base; 1389 1354 1390 1355 #if BOOT_DEBUG_PERI 1391 1392 1393 1394 1395 1356 boot_puts("- coprocessor name : "); 1357 boot_puts(coproc[coproc_id].name); 1358 boot_puts(" / nb ports = "); 1359 boot_putd((unsigned int) coproc[coproc_id].ports); 1360 boot_puts("\n"); 1396 1361 #endif 1397 1362 1398 1363 for (cp_port_id = coproc[coproc_id].port_offset; 1399 1400 cp_port_id++) {1401 //FIXME: the vspace_id should be the same for all ports: put it in the coproc?1364 cp_port_id < coproc[coproc_id].port_offset + coproc[coproc_id].ports; 1365 cp_port_id++) 1366 { 1402 1367 unsigned int vspace_id = cp_port[cp_port_id].vspaceid; 1403 unsigned int vobj_id = cp_port[cp_port_id].mwmr_vobjid + vspace[vspace_id].vobj_offset; 1404 1405 mwmr_channel_t * pmwmr = (mwmr_channel_t *) (vobj[vobj_id].paddr); 1406 1407 if (cp_port[cp_port_id].direction == PORT_TO_COPROC) { 1368 unsigned int vobj_id = cp_port[cp_port_id].mwmr_vobjid + 1369 vspace[vspace_id].vobj_offset; 1370 1371 // Get MWMR channel base address 1372 paddr_t channel_pbase = vobj[vobj_id].paddr; 1373 1374 if (cp_port[cp_port_id].direction == PORT_TO_COPROC) 1375 { 1408 1376 #if BOOT_DEBUG_PERI 1409 boot_puts(" port direction: PORT_TO_COPROC"); 1410 #endif 1411 mwmr_hw_init((void *) cpseg, PORT_TO_COPROC, no_fifo_to, pmwmr); 1377 boot_puts(" port direction: PORT_TO_COPROC"); 1378 #endif 1379 mwmr_hw_init(coproc_pbase, 1380 PORT_TO_COPROC, 1381 no_fifo_to, 1382 channel_pbase); 1412 1383 no_fifo_to++; 1413 1384 } 1414 else { 1385 else 1386 { 1415 1387 #if BOOT_DEBUG_PERI 1416 boot_puts(" port direction: PORT_FROM_COPROC"); 1417 #endif 1418 mwmr_hw_init((void *) cpseg, PORT_FROM_COPROC, no_fifo_from, pmwmr); 1388 boot_puts(" port direction: PORT_FROM_COPROC"); 1389 #endif 1390 mwmr_hw_init(coproc_pbase, 1391 PORT_FROM_COPROC, 1392 no_fifo_from, 1393 channel_pbase); 1419 1394 no_fifo_from++; 1420 1395 } 1421 1396 #if BOOT_DEBUG_PERI 1422 1423 1424 1425 1426 #endif 1427 } 1397 boot_puts(", with mwmr: "); 1398 boot_puts(vobj[vobj_id].name); 1399 boot_puts(" of vspace: "); 1400 boot_puts(vspace[vspace_id].name); 1401 #endif 1402 } // end for cp_ports 1428 1403 } // end for coprocs 1429 1404 } // end for clusters 1430 1405 } // end boot_peripherals_init() 1431 1406 1407 /////////////////////////////////////////////////////////////////////////////// 1408 // This function returns in the vbase and length buffers the virtual base 1409 // address and the length of the segment allocated to the schedulers array 1410 // in the cluster defined by the clusterid argument. 1411 /////////////////////////////////////////////////////////////////////////////// 1412 void boot_get_sched_vaddr( unsigned int cluster_id, 1413 unsigned int* vbase, 1414 unsigned int* length ) 1415 { 1416 mapping_header_t* header = (mapping_header_t *) & seg_mapping_base; 1417 mapping_vobj_t* vobj = boot_get_vobj_base(header); 1418 mapping_vseg_t* vseg = boot_get_vseg_base(header); 1419 mapping_pseg_t* pseg = boot_get_pseg_base(header); 1420 1421 unsigned int vseg_id; 1422 unsigned int found = 0; 1423 1424 for ( vseg_id = 0 ; (vseg_id < header->vsegs) && (found == 0) ; vseg_id++ ) 1425 { 1426 if ( (vobj[vseg[vseg_id].vobj_offset].type == VOBJ_TYPE_SCHED) && 1427 (pseg[vseg[vseg_id].psegid].cluster == cluster_id ) ) 1428 { 1429 *vbase = vseg[vseg_id].vbase; 1430 *length = vobj[vseg[vseg_id].vobj_offset].length; 1431 found = 1; 1432 } 1433 } 1434 if ( found == 0 ) 1435 { 1436 boot_puts("\n[BOOT ERROR] No vobj of type SCHED in cluster "); 1437 boot_putd(cluster_id); 1438 boot_puts("\n"); 1439 boot_exit(); 1440 } 1441 } // end boot_get_sched_vaddr() 1432 1442 1433 1443 /////////////////////////////////////////////////////////////////////////////// 1434 1444 // This function initialises all processors schedulers. 1435 1445 // This is done by processor 0, and the MMU must be activated. 1436 // It initialises the boot_ schedulers_paddr[gpid] pointers array.1446 // It initialises the boot_chedulers[gpid] pointers array. 1437 1447 // Finally, it scan all tasks in all vspaces to initialise the tasks contexts, 1438 1448 // as specified in the mapping_info data structure. 1439 1449 // For each task, a TTY channel, a TIMER channel, a FBDMA channel, and a NIC 1440 // channel can be allocated if required.1450 // channel are allocated if required. 1441 1451 /////////////////////////////////////////////////////////////////////////////// 1442 void boot_schedulers_init() { 1443 mapping_header_t * header = (mapping_header_t *) & seg_mapping_base; 1444 mapping_cluster_t * cluster = boot_get_cluster_base(header); 1445 mapping_pseg_t * pseg = boot_get_pseg_base(header); 1446 mapping_vspace_t * vspace = boot_get_vspace_base(header); 1447 mapping_task_t * task = boot_get_task_base(header); 1448 mapping_vobj_t * vobj = boot_get_vobj_base(header); 1449 mapping_proc_t * proc = boot_get_proc_base(header); 1450 mapping_irq_t * irq = boot_get_irq_base(header); 1451 1452 unsigned int alloc_tty_channel; // TTY channel allocator 1453 unsigned int alloc_nic_channel; // NIC channel allocator 1452 void boot_schedulers_init() 1453 { 1454 mapping_header_t* header = (mapping_header_t *) & seg_mapping_base; 1455 mapping_cluster_t* cluster = boot_get_cluster_base(header); 1456 mapping_vspace_t* vspace = boot_get_vspace_base(header); 1457 mapping_task_t* task = boot_get_task_base(header); 1458 mapping_vobj_t* vobj = boot_get_vobj_base(header); 1459 mapping_proc_t* proc = boot_get_proc_base(header); 1460 mapping_irq_t* irq = boot_get_irq_base(header); 1461 1462 unsigned int cluster_id; // cluster index in mapping_info 1463 unsigned int proc_id; // processor index in mapping_info 1464 unsigned int irq_id; // irq index in mapping_info 1465 unsigned int vspace_id; // vspace index in mapping_info 1466 unsigned int task_id; // task index in mapping_info 1467 1468 unsigned int alloc_tty_channel = 1; // TTY channel allocator 1469 unsigned int alloc_nic_channel = 0; // NIC channel allocator 1470 unsigned int alloc_cma_channel = 0; // CMA channel allocator 1471 unsigned int alloc_ioc_channel = 0; // IOC channel allocator 1454 1472 unsigned int alloc_dma_channel[NB_CLUSTERS]; // DMA channel allocators 1455 unsigned int alloc_timer_channel[NB_CLUSTERS]; // user TIMER allocators 1456 1457 unsigned int cluster_id; // cluster global index 1458 unsigned int proc_id; // processor global index 1459 unsigned int irq_id; // irq global index 1460 unsigned int pseg_id; // pseg global index 1461 unsigned int vspace_id; // vspace global index 1462 unsigned int task_id; // task global index; 1463 1464 // Step 0 : TTY, NIC, TIMERS and DMA channels allocators initialisation 1465 // global_id = cluster_id*NB_*_MAX + loc_id 1466 // - TTY[0] is reserved for the kernel 1467 // - In all clusters the first NB_PROCS_MAX timers 1468 // are reserved for the kernel (context switch) 1469 1470 alloc_tty_channel = 1; 1471 alloc_nic_channel = 0; 1472 1473 for (cluster_id = 0; cluster_id < header->clusters; cluster_id++) { 1473 unsigned int alloc_tim_channel[NB_CLUSTERS]; // user TIMER allocators 1474 1475 ///////////////////////////////////////////////////////////////////////// 1476 // Step 1 : loop on the clusters and on the processors 1477 // to initialize the schedulers[] array of pointers and 1478 // the interrupt vectors. 1479 // Implementation note: 1480 // We need to use both proc_id to scan the mapping info structure, 1481 // and lpid to access the schedulers array. 1482 // - the boot_schedulers[] array of pointers can contain "holes", because 1483 // it is indexed by the global pid = cluster_id*NB_PROCS_MAX + ltid 1484 // - the mapping info array of processors is contiguous, it is indexed 1485 // by proc_id, and use an offset specific in each cluster. 1486 1487 for (cluster_id = 0; cluster_id < header->clusters; cluster_id++) 1488 { 1489 1490 #if BOOT_DEBUG_SCHED 1491 boot_puts("\n[BOOT DEBUG] Initialise schedulers in cluster "); 1492 boot_putd(cluster_id); 1493 boot_puts("\n"); 1494 #endif 1495 1496 // TTY, NIC, CMA, IOC, TIM and DMA channels allocators 1497 // - TTY[0] is reserved for the kernel 1498 // - In all clusters the first NB_PROCS_MAX timers 1499 // are reserved for the kernel (context switch) 1500 1474 1501 alloc_dma_channel[cluster_id] = 0; 1475 alloc_timer_channel[cluster_id] = 0; 1476 } 1477 1478 // Step 1 : loop on the clusters and on the processors 1479 // - initialise the boot_schedulers_paddr[] pointers array 1480 // - initialise the interrupt vectors for each processor. 1481 1482 for (cluster_id = 0; cluster_id < header->clusters; cluster_id++) { 1483 1484 #if BOOT_DEBUG_SCHED 1485 boot_puts("\n[BOOT DEBUG] Initialise schedulers / IT vector in cluster "); 1486 boot_putd(cluster_id); 1487 boot_puts("\n"); 1488 #endif 1489 unsigned int found = 0; 1490 unsigned int pseg_pbase; // pseg base address 1491 unsigned int lpid; // processor local index 1492 1493 // get the physical base address of the first PSEG_TYPE_RAM pseg in cluster 1494 for (pseg_id = cluster[cluster_id].pseg_offset; 1495 pseg_id < cluster[cluster_id].pseg_offset + cluster[cluster_id].psegs; 1496 pseg_id++) { 1497 if (pseg[pseg_id].type == PSEG_TYPE_RAM) { 1498 pseg_pbase = pseg[pseg_id].base; 1499 found = 1; 1500 break; 1501 } 1502 } 1503 1504 if ((cluster[cluster_id].procs > 0) && (found == 0)) { 1505 boot_puts("\n[BOOT ERROR] Missing RAM pseg in cluster "); 1502 alloc_tim_channel[cluster_id] = NB_PROCS_MAX; 1503 1504 unsigned int lpid; // processor local index in cluster 1505 unsigned int sched_vbase; // schedulers segment virtual base address 1506 unsigned int sched_length; // schedulers segment length 1507 unsigned int nprocs; // number of processors in cluster 1508 1509 nprocs = cluster[cluster_id].procs; 1510 1511 // checking processors number 1512 if ( nprocs > NB_PROCS_MAX ) 1513 { 1514 boot_puts("\n[BOOT ERROR] Too much processors in cluster "); 1506 1515 boot_putd(cluster_id); 1507 1516 boot_puts("\n"); 1508 1517 boot_exit(); 1509 1518 } 1510 // 4 Kbytes per scheduler 1511 for (lpid = 0; lpid < cluster[cluster_id].procs; lpid++) { 1512 boot_schedulers_paddr[cluster_id * NB_PROCS_MAX + lpid] = (static_scheduler_t *) (pseg_pbase + (lpid << 12)); 1519 1520 // get scheduler array virtual base address for cluster_id 1521 boot_get_sched_vaddr( cluster_id, &sched_vbase, &sched_length ); 1522 1523 // each processor scheduler requires 1 Kbytes 1524 if ( sched_length < (nprocs<<10) ) 1525 { 1526 boot_puts("\n[BOOT ERROR] Schedulers segment too small in cluster "); 1527 boot_putd(cluster_id); 1528 boot_puts("\n"); 1529 boot_exit(); 1513 1530 } 1514 1531 1515 for (proc_id = cluster[cluster_id].proc_offset; 1516 proc_id < cluster[cluster_id].proc_offset + cluster[cluster_id].procs; 1517 proc_id++) { 1532 for ( proc_id = cluster[cluster_id].proc_offset, lpid = 0 ; 1533 proc_id < cluster[cluster_id].proc_offset + cluster[cluster_id].procs; 1534 proc_id++, lpid++ ) 1535 { 1536 // set the schedulers pointers array 1537 boot_schedulers[cluster_id * NB_PROCS_MAX + lpid] = 1538 (static_scheduler_t*)( sched_vbase + (lpid<<10) ); 1518 1539 1519 1540 #if BOOT_DEBUG_SCHED 1520 boot_puts("\nProc "); 1521 boot_putd(proc_id); 1522 boot_puts(" : scheduler pbase = "); 1523 boot_putx(pseg_pbase + (proc_id << 12)); 1524 boot_puts("\n"); 1525 #endif 1526 // initialise the "tasks" variable in scheduler 1527 boot_scheduler_set_tasks(proc_id, 0); 1541 boot_puts("\nProc "); 1542 boot_putd(lpid); 1543 boot_puts(" : scheduler virtual base address = "); 1544 boot_putx( sched_vbase + (lpid<<10) ); 1545 boot_puts("\n"); 1546 #endif 1547 // current processor scheduler pointer : psched 1548 static_scheduler_t* psched = (static_scheduler_t*)(sched_vbase+(lpid<<10)); 1549 1550 // initialise the "tasks" variable 1551 psched->tasks = 0; 1528 1552 1529 1553 // initialise the interrupt_vector with ISR_DEFAULT 1530 1554 unsigned int slot; 1531 for (slot = 0; slot < 32; slot++) { 1532 boot_scheduler_set_itvector(proc_id, slot, 0); 1533 } 1555 for (slot = 0; slot < 32; slot++) psched->interrupt_vector[slot] = 0; 1534 1556 1535 1557 // scan the IRQs actually allocated to current processor 1536 1558 for (irq_id = proc[proc_id].irq_offset; 1537 irq_id < proc[proc_id].irq_offset + proc[proc_id].irqs; 1538 irq_id++) { 1559 irq_id < proc[proc_id].irq_offset + proc[proc_id].irqs; 1560 irq_id++) 1561 { 1539 1562 unsigned int type = irq[irq_id].type; 1540 1563 unsigned int icu_id = irq[irq_id].icuid; … … 1542 1565 unsigned int channel = irq[irq_id].channel; 1543 1566 unsigned int value = isr_id | (type << 8) | (channel << 16); 1544 boot_scheduler_set_itvector(proc_id, icu_id, value);1567 psched->interrupt_vector[icu_id] = value; 1545 1568 1546 1569 #if BOOT_DEBUG_SCHED 1547 boot_puts("- IRQ : icu = "); 1548 boot_putd(icu_id); 1549 boot_puts(" / type = "); 1550 boot_putd(type); 1551 boot_puts(" / isr = "); 1552 boot_putd(isr_id); 1553 boot_puts(" / channel = "); 1554 boot_putd(channel); 1555 boot_puts("\n"); 1570 boot_puts("- IRQ : icu = "); 1571 boot_putd(icu_id); 1572 boot_puts(" / type = "); 1573 boot_putd(type); 1574 boot_puts(" / isr = "); 1575 boot_putd(isr_id); 1576 boot_puts(" / channel = "); 1577 boot_putd(channel); 1578 boot_puts(" => vector_entry = "); 1579 boot_putx( value ); 1580 boot_puts("\n"); 1556 1581 #endif 1557 1582 } … … 1559 1584 } // end for clusters 1560 1585 1586 /////////////////////////////////////////////////////////////////// 1561 1587 // Step 2 : loop on the vspaces and the tasks 1562 1588 // to initialise the schedulers and the task contexts. 1563 1564 for (vspace_id = 0; vspace_id < header->vspaces; vspace_id++) { 1589 // Implementation note: 1590 // This function initialises the task context for all tasks. 1591 // For each processor, the scheduler virtual base address 1592 // is written in the CP0_SCHED register in reset.S 1593 1594 for (vspace_id = 0; vspace_id < header->vspaces; vspace_id++) 1595 { 1565 1596 1566 1597 #if BOOT_DEBUG_SCHED 1567 boot_puts 1568 ("\n[BOOT DEBUG] Initialise schedulers / task contexts for vspace "); 1569 boot_puts(vspace[vspace_id].name); 1570 boot_puts("\n"); 1598 boot_puts("\n[BOOT DEBUG] Initialise task contexts for vspace "); 1599 boot_puts(vspace[vspace_id].name); 1600 boot_puts("\n"); 1571 1601 #endif 1572 1602 // We must set the PTPR depending on the vspace, because the start_vector 1573 1603 // and the stack address are defined in virtual space. 1574 boot_set_mmu_ptpr( (unsigned int) boot_ptabs_paddr[vspace_id] >> 13);1604 boot_set_mmu_ptpr( (unsigned int)(boot_ptabs_paddr[vspace_id] >> 13) ); 1575 1605 1576 1606 // loop on the tasks in vspace (task_id is the global index) 1577 1607 for (task_id = vspace[vspace_id].task_offset; 1578 task_id < (vspace[vspace_id].task_offset + vspace[vspace_id].tasks); 1579 task_id++) { 1608 task_id < (vspace[vspace_id].task_offset + vspace[vspace_id].tasks); 1609 task_id++) 1610 { 1611 // compute gpid (global processor index) and scheduler base address 1612 unsigned int gpid = task[task_id].clusterid * NB_PROCS_MAX + 1613 task[task_id].proclocid; 1614 static_scheduler_t* psched = boot_schedulers[gpid]; 1615 1580 1616 // ctx_ra : the return address is &boot_eret() 1581 1617 unsigned int ctx_ra = (unsigned int) &boot_eret; … … 1585 1621 1586 1622 // ctx_ptpr : page table physical base address (shifted by 13 bit) 1587 unsigned int ctx_ptpr = (unsigned int) boot_ptabs_paddr[vspace_id] >> 13; 1588 1589 // compute gpid = global processor index 1590 unsigned int gpid = task[task_id].clusterid * NB_PROCS_MAX + task[task_id].proclocid; 1623 unsigned int ctx_ptpr = (unsigned int)(boot_ptabs_paddr[vspace_id] >> 13); 1591 1624 1592 1625 // ctx_ptab : page_table virtual base address 1593 unsigned int ctx_ptab = (unsigned int)boot_ptabs_vaddr[vspace_id];1594 1595 // ctx_tty : terminal global index provided by aglobal allocator1626 unsigned int ctx_ptab = boot_ptabs_vaddr[vspace_id]; 1627 1628 // ctx_tty : terminal global index provided by the global allocator 1596 1629 unsigned int ctx_tty = 0xFFFFFFFF; 1597 if (task[task_id].use_tty) { 1598 if (alloc_tty_channel >= NB_TTYS) { 1630 if (task[task_id].use_tty) 1631 { 1632 if (alloc_tty_channel >= NB_TTY_CHANNELS) 1633 { 1599 1634 boot_puts("\n[BOOT ERROR] TTY index too large for task "); 1600 1635 boot_puts(task[task_id].name); … … 1607 1642 alloc_tty_channel++; 1608 1643 } 1609 // ctx_nic : NIC channel global index provided by aglobal allocator1644 // ctx_nic : NIC channel global index provided by the global allocator 1610 1645 unsigned int ctx_nic = 0xFFFFFFFF; 1611 if (task[task_id].use_nic) { 1612 if (alloc_nic_channel >= NB_NICS) { 1646 if (task[task_id].use_nic) 1647 { 1648 if (alloc_nic_channel >= NB_NIC_CHANNELS) 1649 { 1613 1650 boot_puts("\n[BOOT ERROR] NIC channel index too large for task "); 1614 1651 boot_puts(task[task_id].name); … … 1621 1658 alloc_nic_channel++; 1622 1659 } 1623 // ctx_timer : user TIMER global index provided by a cluster allocator 1624 unsigned int ctx_timer = 0xFFFFFFFF; 1625 if (task[task_id].use_timer) { 1660 // ctx_cma : CMA channel global index provided by the global allocator 1661 unsigned int ctx_cma = 0xFFFFFFFF; 1662 if (task[task_id].use_cma) 1663 { 1664 if (alloc_cma_channel >= NB_CMA_CHANNELS) 1665 { 1666 boot_puts("\n[BOOT ERROR] CMA channel index too large for task "); 1667 boot_puts(task[task_id].name); 1668 boot_puts(" in vspace "); 1669 boot_puts(vspace[vspace_id].name); 1670 boot_puts("\n"); 1671 boot_exit(); 1672 } 1673 ctx_cma = alloc_cma_channel; 1674 alloc_cma_channel++; 1675 } 1676 // ctx_ioc : IOC channel global index provided by the global allocator 1677 unsigned int ctx_ioc = 0xFFFFFFFF; 1678 if (task[task_id].use_ioc) 1679 { 1680 if (alloc_ioc_channel >= NB_IOC_CHANNELS) 1681 { 1682 boot_puts("\n[BOOT ERROR] IOC channel index too large for task "); 1683 boot_puts(task[task_id].name); 1684 boot_puts(" in vspace "); 1685 boot_puts(vspace[vspace_id].name); 1686 boot_puts("\n"); 1687 boot_exit(); 1688 } 1689 ctx_ioc = alloc_ioc_channel; 1690 alloc_ioc_channel++; 1691 } 1692 // ctx_tim : TIMER local channel index provided by the cluster allocator 1693 unsigned int ctx_tim = 0xFFFFFFFF; 1694 if (task[task_id].use_tim) 1695 { 1626 1696 unsigned int cluster_id = task[task_id].clusterid; 1627 unsigned int allocated = alloc_timer_channel[cluster_id]; 1628 1629 if (allocated >= NB_TIMERS_MAX){1697 1698 if ( alloc_tim_channel[cluster_id] >= NB_TIM_CHANNELS ) 1699 { 1630 1700 boot_puts("\n[BOOT ERROR] local TIMER index too large for task "); 1631 1701 boot_puts(task[task_id].name); … … 1635 1705 boot_exit(); 1636 1706 } 1637 //assert(allocated >= 0); 1638 char found = 0;1639 for (irq_id = 0; irq_id < 32; irq_id++) { //look at the isr_timer isr channel1640 unsigned int isr = boot_scheduler_get_itvector(gpid, irq_id) & 0x000000FF;1641 if (isr == ISR_TIMER){1642 if (allocated == 0) {1643 found = 1;1644 alloc_timer_channel[cluster_id]++;1645 ctx_timer = cluster_id * NB_TIMERS_MAX + alloc_timer_channel[cluster_id];1646 break;1647 }1648 else {1649 allocated--;1650 }1707 1708 // checking that there is a well defined ISR_TIMER installed 1709 unsigned int found = 0; 1710 for ( irq_id = 0 ; irq_id < 32 ; irq_id++ ) 1711 { 1712 unsigned int entry = psched->interrupt_vector[irq_id]; 1713 unsigned int isr = entry & 0x000000FF; 1714 unsigned int channel = entry>>16; 1715 if ( (isr == ISR_TIMER) && (channel == alloc_tim_channel[cluster_id]) ) 1716 { 1717 found = 1; 1718 ctx_tim = alloc_tim_channel[cluster_id]; 1719 alloc_tim_channel[cluster_id]++; 1720 break; 1651 1721 } 1652 1722 } 1653 1654 if (!found){1655 boot_puts("\n[BOOT ERROR] No user timer availablefor task ");1723 if (!found) 1724 { 1725 boot_puts("\n[BOOT ERROR] No ISR_TIMER installed for task "); 1656 1726 boot_puts(task[task_id].name); 1657 1727 boot_puts(" in vspace "); … … 1660 1730 boot_exit(); 1661 1731 } 1662 1663 1732 } 1664 // ctx_dma : DMA global index provided by a cluster allocator 1733 // ctx_dma : the local channel index is defined by the cluster allocator 1734 // but the ctx_dma value is a global index 1665 1735 unsigned int ctx_dma = 0xFFFFFFFF; 1666 if (task[task_id].use_fbdma || task[task_id].use_nic) { 1736 if ( task[task_id].use_dma ) 1737 { 1667 1738 unsigned int cluster_id = task[task_id].clusterid; 1668 if (alloc_dma_channel[cluster_id] >= NB_DMAS_MAX) { 1739 1740 if (alloc_dma_channel[cluster_id] >= NB_DMA_CHANNELS) 1741 { 1669 1742 boot_puts("\n[BOOT ERROR] local DMA index too large for task "); 1670 1743 boot_puts(task[task_id].name); … … 1674 1747 boot_exit(); 1675 1748 } 1676 ctx_dma = cluster_id * NB_DMA S_MAX+ alloc_dma_channel[cluster_id];1749 ctx_dma = cluster_id * NB_DMA_CHANNELS + alloc_dma_channel[cluster_id]; 1677 1750 alloc_dma_channel[cluster_id]++; 1678 1751 } 1679 1752 // ctx_epc : Get the virtual address of the start function 1680 mapping_vobj_t * pvobj = &vobj[vspace[vspace_id].vobj_offset + vspace[vspace_id].start_offset]; 1681 unsigned int * start_vector_vbase = (unsigned int *) pvobj->vaddr; 1753 mapping_vobj_t* pvobj = &vobj[vspace[vspace_id].vobj_offset + 1754 vspace[vspace_id].start_offset]; 1755 unsigned int* start_vector_vbase = (unsigned int *) pvobj->vaddr; 1682 1756 unsigned int ctx_epc = start_vector_vbase[task[task_id].startid]; 1683 1757 … … 1686 1760 unsigned int ctx_sp = vobj[vobj_id].vaddr + vobj[vobj_id].length; 1687 1761 1688 // In the code below, we access the scheduler with specific access 1689 // functions, because we only have the physical address of the scheduler, 1690 // and these functions must temporary desactivate the DTLB... 1691 1692 // get local task index in scheduler[gpid] 1693 unsigned int ltid = boot_scheduler_get_tasks(gpid); 1694 1695 if (ltid >= IDLE_TASK_INDEX) { 1762 // get local task index in scheduler 1763 unsigned int ltid = psched->tasks; 1764 1765 if (ltid >= IDLE_TASK_INDEX) 1766 { 1696 1767 boot_puts("\n[BOOT ERROR] : "); 1697 1768 boot_putd(ltid); … … 1701 1772 boot_exit(); 1702 1773 } 1703 // update the "tasks" field in scheduler[gpid] 1704 boot_scheduler_set_tasks(gpid, ltid + 1); 1705 1706 // update the "current" field in scheduler[gpid] 1707 boot_scheduler_set_current(gpid, 0); 1708 1709 // initializes the task context in scheduler[gpid] 1710 boot_scheduler_set_context(gpid, ltid, CTX_SR_ID, ctx_sr); 1711 boot_scheduler_set_context(gpid, ltid, CTX_SP_ID, ctx_sp); 1712 boot_scheduler_set_context(gpid, ltid, CTX_RA_ID, ctx_ra); 1713 boot_scheduler_set_context(gpid, ltid, CTX_EPC_ID, ctx_epc); 1714 boot_scheduler_set_context(gpid, ltid, CTX_PTPR_ID, ctx_ptpr); 1715 boot_scheduler_set_context(gpid, ltid, CTX_TTY_ID, ctx_tty); 1716 boot_scheduler_set_context(gpid, ltid, CTX_DMA_ID, ctx_dma); 1717 boot_scheduler_set_context(gpid, ltid, CTX_NIC_ID, ctx_nic); 1718 boot_scheduler_set_context(gpid, ltid, CTX_TIMER_ID, ctx_timer); 1719 boot_scheduler_set_context(gpid, ltid, CTX_PTAB_ID, ctx_ptab); 1720 boot_scheduler_set_context(gpid, ltid, CTX_LTID_ID, ltid); 1721 boot_scheduler_set_context(gpid, ltid, CTX_VSID_ID, vspace_id); 1722 boot_scheduler_set_context(gpid, ltid, CTX_GTID_ID, task_id); 1723 boot_scheduler_set_context(gpid, ltid, CTX_RUN_ID, 1); 1774 // update the "tasks" field in scheduler 1775 psched->tasks = ltid + 1; 1776 1777 // update the "current" field in scheduler 1778 psched->current = 0; 1779 1780 // initializes the task context in scheduler 1781 psched->context[ltid][CTX_SR_ID] = ctx_sr; 1782 psched->context[ltid][CTX_SP_ID] = ctx_sp; 1783 psched->context[ltid][CTX_RA_ID] = ctx_ra; 1784 psched->context[ltid][CTX_EPC_ID] = ctx_epc; 1785 psched->context[ltid][CTX_PTPR_ID] = ctx_ptpr; 1786 psched->context[ltid][CTX_TTY_ID] = ctx_tty; 1787 psched->context[ltid][CTX_CMA_ID] = ctx_cma; 1788 psched->context[ltid][CTX_IOC_ID] = ctx_ioc; 1789 psched->context[ltid][CTX_NIC_ID] = ctx_nic; 1790 psched->context[ltid][CTX_TIM_ID] = ctx_tim; 1791 psched->context[ltid][CTX_DMA_ID] = ctx_dma; 1792 psched->context[ltid][CTX_PTAB_ID] = ctx_ptab; 1793 psched->context[ltid][CTX_LTID_ID] = ltid; 1794 psched->context[ltid][CTX_GTID_ID] = task_id; 1795 psched->context[ltid][CTX_VSID_ID] = vspace_id; 1796 psched->context[ltid][CTX_RUN_ID] = 1; 1724 1797 1725 1798 #if BOOT_DEBUG_SCHED 1726 boot_puts("\nTask "); 1727 boot_puts(task[task_id].name); 1728 boot_puts(" ("); 1729 boot_putd(task_id); 1730 boot_puts(") allocated to processor "); 1731 boot_putd(gpid); 1732 boot_puts("\n - ctx[LTID] = "); 1733 boot_putd(ltid); 1734 boot_puts("\n - ctx[SR] = "); 1735 boot_putx(ctx_sr); 1736 boot_puts("\n - ctx[SR] = "); 1737 boot_putx(ctx_sp); 1738 boot_puts("\n - ctx[RA] = "); 1739 boot_putx(ctx_ra); 1740 boot_puts("\n - ctx[EPC] = "); 1741 boot_putx(ctx_epc); 1742 boot_puts("\n - ctx[PTPR] = "); 1743 boot_putx(ctx_ptpr); 1744 boot_puts("\n - ctx[TTY] = "); 1745 boot_putd(ctx_tty); 1746 boot_puts("\n - ctx[NIC] = "); 1747 boot_putd(ctx_nic); 1748 boot_puts("\n - ctx[TIMER] = "); 1749 boot_putd(ctx_timer); 1750 boot_puts("\n - ctx[DMA] = "); 1751 boot_putd(ctx_dma); 1752 boot_puts("\n - ctx[PTAB] = "); 1753 boot_putx(ctx_ptab); 1754 boot_puts("\n - ctx[VSID] = "); 1755 boot_putd(vspace_id); 1756 boot_puts("\n"); 1799 boot_puts("\nTask "); 1800 boot_puts(task[task_id].name); 1801 boot_puts(" ("); 1802 boot_putd(task_id); 1803 boot_puts(") allocated to processor "); 1804 boot_putd(gpid); 1805 boot_puts("\n - ctx[LTID] = "); 1806 boot_putd(ltid); 1807 boot_puts("\n - ctx[SR] = "); 1808 boot_putx(ctx_sr); 1809 boot_puts("\n - ctx[SR] = "); 1810 boot_putx(ctx_sp); 1811 boot_puts("\n - ctx[RA] = "); 1812 boot_putx(ctx_ra); 1813 boot_puts("\n - ctx[EPC] = "); 1814 boot_putx(ctx_epc); 1815 boot_puts("\n - ctx[PTPR] = "); 1816 boot_putx(ctx_ptpr); 1817 boot_puts("\n - ctx[TTY] = "); 1818 boot_putd(ctx_tty); 1819 boot_puts("\n - ctx[NIC] = "); 1820 boot_putd(ctx_nic); 1821 boot_puts("\n - ctx[CMA] = "); 1822 boot_putd(ctx_cma); 1823 boot_puts("\n - ctx[IOC] = "); 1824 boot_putd(ctx_ioc); 1825 boot_puts("\n - ctx[TIM] = "); 1826 boot_putd(ctx_tim); 1827 boot_puts("\n - ctx[DMA] = "); 1828 boot_putd(ctx_dma); 1829 boot_puts("\n - ctx[PTAB] = "); 1830 boot_putx(ctx_ptab); 1831 boot_puts("\n - ctx[GTID] = "); 1832 boot_putd(task_id); 1833 boot_puts("\n - ctx[VSID] = "); 1834 boot_putd(vspace_id); 1835 boot_puts("\n"); 1757 1836 #endif 1758 1837 … … 1765 1844 // This function is executed by P[0] to wakeup all processors. 1766 1845 ////////////////////////////////////////////////////////////////////////////////// 1767 void boot_start_all_procs() { 1846 void boot_start_all_procs() 1847 { 1768 1848 mapping_header_t * header = (mapping_header_t *) &seg_mapping_base; 1769 1849 header->signature = OUT_MAPPING_SIGNATURE; … … 1786 1866 boot_psegs_init(); 1787 1867 1788 boot_puts 1789 ("\n[BOOT] Pseg allocators initialisation completed at cycle "); 1868 boot_puts("\n[BOOT] Pseg allocators initialisation completed at cycle "); 1790 1869 boot_putd(boot_proctime()); 1791 1870 boot_puts("\n"); … … 1798 1877 boot_puts("\n"); 1799 1878 1879 // mmu activation ( with page table [Ã] ) 1880 boot_set_mmu_ptpr( (unsigned int)(boot_ptabs_paddr[0] >> 13) ); 1881 boot_set_mmu_mode(0xF); 1882 1883 boot_puts("\n[BOOT] Proc 0 MMU activation at cycle "); 1884 boot_putd(boot_proctime()); 1885 boot_puts("\n"); 1886 1800 1887 // vobjs initialisation 1801 1888 boot_vobjs_init(); … … 1809 1896 1810 1897 boot_puts("\n[BOOT] Peripherals initialisation completed at cycle "); 1811 boot_putd(boot_proctime());1812 boot_puts("\n");1813 1814 // mmu activation1815 boot_set_mmu_ptpr((unsigned int) boot_ptabs_paddr[0] >> 13);1816 boot_set_mmu_mode(0xF);1817 1818 boot_puts("\n[BOOT] MMU activation completed at cycle ");1819 1898 boot_putd(boot_proctime()); 1820 1899 boot_puts("\n"); -
soft/giet_vm/boot/reset.S
r234 r238 182 182 boot_to_kernel_init: 183 183 184 # all processors initialise SCHED register with boot_schedulers_paddr[pid] 184 # all processors initialise the CP0 SCHED register 185 # SCHED contains the schedulers array virtual base address 185 186 mfc0 k0, CP0_PROCID 186 187 andi k0, k0, 0xFFF 187 188 sll k0, k0, 2 # k0 <= 4*pid 188 la k1, boot_schedulers_paddr 189 addu k1, k1, k0 # k1 <= &boot_scheduler_paddr[pid] 190 lw k1, 0(k1) 191 mtc0 k1, CP0_SCHED 192 193 # all processors initialize PTPR register with boot_ptabs_paddr[0] 189 la k1, boot_schedulers 190 addu k1, k1, k0 # k1 <= &boot_schedulers[pid] 191 lw k0, 0(k1) 192 mtc0 k0, CP0_SCHED 193 194 # all processors initialize the CP2 PTPR register 195 # At this stage, all PTPR registers contain the physical base 196 # address (13 bits right shifted) of the page table for vspace[0] 194 197 la k1, boot_ptabs_paddr 195 lw k1, 0(k1) 196 srl k1, k1, 13 197 mtc2 k1, CP2_PTPR 198 199 # all processors activate MMU 198 lw k0, 0(k1) # k0 <= paddr_lsb 199 lw k1, 4(k1) # k1 <= paddr_msb 200 srl k0, k0, 13 # k0 <= paddr_lsb shifted 201 sll k1, k1, 19 # k1 <= paddr_msb shifted 202 or k0, k0, k1 203 mtc2 k0, CP2_PTPR 204 205 # all processors activate MMU (already done for processor 0) 200 206 li k1, 0xF 201 207 mtc2 k1, CP2_MODE
Note: See TracChangeset
for help on using the changeset viewer.