Changeset 189 for soft/giet_vm/sys/kernel_init.c
- Timestamp:
- Aug 7, 2012, 6:37:49 PM (12 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
soft/giet_vm/sys/kernel_init.c
r185 r189 5 5 // Copyright (c) UPMC-LIP6 6 6 //////////////////////////////////////////////////////////////////////////////////// 7 // FIXME8 7 // The kernel_init.c files is part of the GIET-VM nano-kernel. 9 // It contains the kernel entry point for the second phase of system initialisation:10 // all processors are jumping to _kernel_init, but P[0] is first because other11 // processors are blocked until P[0] complete initilisation of task contexts,12 // vobjs and peripherals.13 // All procs in this phase have their MMU activated, because each processor P[i]14 // must initialise registers SP, SR, PTPR and EPC with informations stored15 // in _scheduler[i].8 // It contains the kernel entry point for the last step of system initialisation. 9 // All procs in this phase have their MMU activated, and are running in parallel. 10 // - each processor updates its own scheduler, to replace the ISR index 11 // by the actual ISR virtual address, and set its own entry in the 12 // kernel _schedulers_paddr[] array. 13 // - each processor initialises the SP, SR, PTPR, EPC registers, and starts 14 // its private Timer, before jumping to the user code with an eret. 16 15 //////////////////////////////////////////////////////////////////////////////////// 17 16 18 17 #include <common.h> 18 #include <irq_handler.h> 19 19 #include <ctx_handler.h> 20 20 #include <sys_handler.h> … … 29 29 #include <drivers.h> 30 30 31 #define in_kinit __attribute__((section (".kinit")))32 33 31 /////////////////////////////////////////////////////////////////////////////////// 34 // array of pointers on the page tables 35 // (both physical and virtual addresses) 32 // Kernel Global variables 36 33 /////////////////////////////////////////////////////////////////////////////////// 37 34 38 __attribute__((section (".kdata"))) unsigned int _kernel_ptabs_paddr[GIET_NB_VSPACE_MAX];39 __attribute__((section (".kdata"))) unsigned int _kernel_ptabs_vaddr[GIET_NB_VSPACE_MAX];35 __attribute__((section (".kdata"))) 36 page_table_t* _ptabs_paddr[GIET_NB_VSPACE_MAX]; 40 37 41 /////////////////////////////////////////////////////////////////////////////////// 42 // declarations required to avoid forward references 43 /////////////////////////////////////////////////////////////////////////////////// 38 __attribute__((section (".kdata"))) 39 page_table_t* _ptabs_vaddr[GIET_NB_VSPACE_MAX]; 44 40 45 void _kernel_ptabs_init(void); 46 void _kernel_vobjs_init(void); 47 void _kernel_tasks_init(void); 48 void _kernel_peripherals_init(void); 49 void _kernel_interrupt_vector_init(void); 50 void _kernel_start_all_procs(void); 41 __attribute__((section (".kdata"))) 42 static_scheduler_t* _schedulers_paddr[NB_CLUSTERS*NB_PROCS_MAX]; 51 43 52 44 ////////////////////////////////////////////////////////////////////////////////// 53 // This function is the entry point for the secondstep of the boot sequence.45 // This function is the entry point for the last step of the boot sequence. 54 46 ////////////////////////////////////////////////////////////////////////////////// 55 in_kinitvoid _kernel_init()47 __attribute__((section (".kinit"))) void _kernel_init() 56 48 { 57 49 // values to be written in registers … … 61 53 unsigned int epc_value; 62 54 63 unsigned int pid = _procid(); 55 unsigned int proc_id = _procid(); 56 unsigned int cluster_id = proc_id / NB_PROCS_MAX; 57 unsigned int lpid = proc_id % NB_PROCS_MAX; 64 58 65 // only processor 0 executes system initialisation 66 if ( pid == 0 ) 59 // step 1 : Initialise scheduler physical addresses array 60 61 // get scheduler physical address from register 62 static_scheduler_t* psched = (static_scheduler_t*)_get_sched(); 63 _schedulers_paddr[proc_id] = psched; 64 65 #if GIET_DEBUG_INIT 66 _get_lock(&_tty_put_lock); 67 _puts("\n[GIET DEBUG] step 1 for processor "); 68 _putw( proc_id ); 69 _puts("\n"); 70 _puts("- scheduler pbase = "); 71 _putw( (unsigned int)psched ); 72 _puts("\n"); 73 _release_lock(&_tty_put_lock); 74 #endif 75 76 // step 2 : compute and set ICU mask 77 unsigned int irq_id; 78 unsigned int mask = 0; 79 for ( irq_id = 0 ; irq_id < 32 ; irq_id++ ) 67 80 { 68 _kernel_ptabs_init(); 69 /* must be called after the initialisation of ptabs */ 70 _kernel_vobjs_init(); 71 _kernel_tasks_init(); 72 _kernel_interrupt_vector_init(); 73 _kernel_peripherals_init(); 74 _kernel_start_all_procs(); 81 unsigned int entry = _get_interrupt_vector_entry(irq_id); 82 if ( entry ) mask = mask | 0x1<< irq_id; 75 83 } 84 _icu_write( cluster_id, 85 lpid, 86 ICU_MASK_SET, 87 mask ); 88 89 #if GIET_DEBUG_INIT 90 _get_lock(&_tty_put_lock); 91 _puts("\n[GIET DEBUG] step 2 for processor "); 92 _putw( proc_id ); 93 _puts("\n"); 94 _puts("- ICU mask = "); 95 _putw( mask ); 96 _puts("\n"); 97 _release_lock(&_tty_put_lock); 98 #endif 76 99 77 // each processor initialises it's SP, SR, PTPR, and EPC registers78 // from values defined in _scheduler[pid], starts it's private79 // context switch timer (if there is more than one task allocated)80 // and jumps to user code.81 // It does nothing, and keep idle if no task allocated.82 100 83 static_scheduler_t* sched = &_scheduler[pid];101 // step 3 : TODO initialise page table addresse arrays 84 102 85 if ( sched->tasks ) // at leat one task allocated 103 104 // step 4 : start TICK timer if more than one task 105 unsigned int tasks = _get_tasks_number(); 106 if ( tasks > 1 ) 107 { 108 unsigned int period = GIET_TICK_VALUE; 109 unsigned int mode = 0x3; 110 _timer_access( 0, // write access 111 cluster_id, 112 proc_id, 113 TIMER_PERIOD, 114 &period ); 115 _timer_access( 0, // write access 116 cluster_id, 117 proc_id, 118 TIMER_MODE, 119 &mode ); 120 121 #if GIET_DEBUG_INIT 122 _get_lock(&_tty_put_lock); 123 _puts("\n[GIET DEBUG] Step 4 for processor "); 124 _putw( proc_id ); 125 _puts("\n"); 126 _puts("- TICK period = "); 127 _putd( period ); 128 _puts("\n"); 129 _release_lock(&_tty_put_lock); 130 #endif 131 132 } 133 134 // step 5 : each processor initialises SP, SR, PTPR, EPC, registers 135 // with the values corresponding to the first allocated task, 136 // It does nothing, and keep idle if no task allocated. 137 138 if ( tasks ) // at leat one task allocated 86 139 { 87 140 // initialise registers 88 sp_value = sched->context[0][CTX_SP_ID];89 sr_value = sched->context[0][CTX_SR_ID];90 ptpr_value = sched->context[0][CTX_PTPR_ID];91 epc_value = sched->context[0][CTX_EPC_ID];141 sp_value = _get_current_context_slot(CTX_SP_ID); 142 sr_value = _get_current_context_slot(CTX_SR_ID); 143 ptpr_value = _get_current_context_slot(CTX_PTPR_ID); 144 epc_value = _get_current_context_slot(CTX_EPC_ID); 92 145 93 // start TICK timer 94 if ( sched->tasks > 1 ) 95 { 96 unsigned int cluster_id = pid / NB_PROCS; 97 unsigned int proc_id = pid % NB_PROCS; 98 _timer_write( cluster_id, proc_id, TIMER_PERIOD, GIET_TICK_VALUE ); 99 _timer_write( cluster_id, proc_id, TIMER_MODE , 0x3 ); 100 } 146 #if GIET_DEBUG_INIT 147 _get_lock(&_tty_put_lock); 148 _puts("\n[GIET DEBUG] step 5 for processor "); 149 _putw( proc_id ); 150 _puts("\n"); 151 _puts("- sp = "); 152 _putw( sp_value ); 153 _puts("\n"); 154 _puts("- sr = "); 155 _putw( sr_value ); 156 _puts("\n"); 157 _puts("- ptpr = "); 158 _putw( ptpr_value<<13 ); 159 _puts("\n"); 160 _puts("- epc = "); 161 _putw( epc_value ); 162 _puts("\n"); 163 _release_lock(&_tty_put_lock); 164 #endif 101 165 } 102 166 else // no task allocated … … 104 168 _get_lock( &_tty_put_lock ); 105 169 _puts("\n No task allocated to processor "); 106 _putw( p id );170 _putw( proc_id ); 107 171 _puts(" => keep idle\n"); 108 172 _release_lock ( &_tty_put_lock ); … … 117 181 } 118 182 183 // set critical registers and jump to user code 119 184 asm volatile ( 120 185 "move $29, %0 \n" /* SP <= ctx[CTX_SP_ID] */ … … 128 193 129 194 } // end _kernel_init() 130 131 //////////////////////////////////////////////////////////////////////////////////132 // This function wakeup all processors.133 // It should be executed by P[0] when the kernel initialisation is done.134 //////////////////////////////////////////////////////////////////////////////////135 in_kinit void _kernel_start_all_procs()136 {137 mapping_header_t* header = (mapping_header_t*)&seg_mapping_base;138 139 _puts("\n[INIT] Starting parallel execution at cycle : ");140 _putw( _proctime() );141 _puts("\n");142 143 header->signature = OUT_MAPPING_SIGNATURE;144 }145 146 //////////////////////////////////////////////////////////////////////////////////147 // _eret()148 // The address of this function is used to initialise the return address (RA)149 // in all task contexts (when the task has never been executed.150 //////////////////////////////////////////////////////////////////////////////////151 in_kinit void _eret()152 {153 asm volatile("eret \n"154 "nop");155 }156 157 ///////////////////////////////////////////////////////////////////////////////158 // used to access user space159 ///////////////////////////////////////////////////////////////////////////////160 void _set_ptpr(unsigned int vspace_id)161 {162 unsigned int ptpr = ((unsigned int)_kernel_ptabs_paddr[vspace_id]) >> 13;163 asm volatile("mtc2 %0, $0"::"r"(ptpr));164 }165 166 ///////////////////////////////////////////////////////////////////////////////167 // This function initialises the _kernel_ptabs_paddr[] array indexed by the vspace_id,168 // and containing the base addresses of all page tables.169 // This _kernel_ptabs_paddr[] array is used to initialise the task contexts.170 ///////////////////////////////////////////////////////////////////////////////171 in_kinit void _kernel_ptabs_init()172 {173 mapping_header_t* header = (mapping_header_t*)&seg_mapping_base;174 mapping_vspace_t* vspace = _get_vspace_base( header );175 mapping_vobj_t* vobj = _get_vobj_base( header );176 177 unsigned int vspace_id;178 unsigned int vobj_id;179 180 // loop on the vspaces181 for ( vspace_id = 0 ; vspace_id < header->vspaces ; vspace_id++ )182 {183 char ptab_found = 0;184 185 #if INIT_DEBUG_CTX186 _puts("[INIT] --- ptabs initialisation in vspace ");187 _puts(vspace[vspace_id].name);188 _puts("\n");189 #endif190 // loop on the vobjs and get the ptpr191 for(vobj_id= vspace[vspace_id].vobj_offset;192 vobj_id < (vspace[vspace_id].vobj_offset+ vspace[vspace_id].vobjs);193 vobj_id++)194 {195 if(vobj[vobj_id].type == VOBJ_TYPE_PTAB)196 {197 if( ptab_found )198 {199 _puts("\n[INIT ERROR] Only one PTAB for by vspace ");200 _putw( vspace_id );201 _exit();202 }203 204 ptab_found = 1;205 _kernel_ptabs_paddr[vspace_id] = vobj[vobj_id].paddr;206 _kernel_ptabs_vaddr[vspace_id] = vobj[vobj_id].vaddr;207 208 #if INIT_DEBUG_CTX209 _puts("[INIT] PTAB address = ");210 _putw(_kernel_ptabs_paddr[vspace_id]);211 _puts("\n");212 #endif213 }214 215 }216 217 if( !ptab_found )218 {219 _puts("\n[INIT ERROR] Missing PTAB for vspace ");220 _putw( vspace_id );221 _exit();222 }223 }224 225 _puts("\n[INIT] Ptabs initialisation completed at cycle : ");226 _putw( _proctime() );227 _puts("\n");228 229 } // end kernel_ptabs_init()230 231 ///////////////////////////////////////////////////////////////////////////////232 // This function initializes all private vobjs defined in the vspaces,233 // such as mwmr channels, barriers and locks, depending on the vobj type.234 // (Most of the vobjs are not known, and not initialised by the compiler).235 ///////////////////////////////////////////////////////////////////////////////236 in_kinit void _kernel_vobjs_init()237 {238 mapping_header_t* header = (mapping_header_t*)&seg_mapping_base;239 mapping_vspace_t* vspace = _get_vspace_base( header );240 mapping_vobj_t* vobj = _get_vobj_base( header );241 242 unsigned int vspace_id;243 unsigned int vobj_id;244 245 // loop on the vspaces246 for ( vspace_id = 0 ; vspace_id < header->vspaces ; vspace_id++ )247 {248 249 #if INIT_DEBUG_CTX250 _puts("[INIT] --- vobjs initialisation in vspace ");251 _puts(vspace[vspace_id].name);252 _puts("\n");253 #endif254 /** Set the current vspace ptpr to initialise the vobjs */255 _set_ptpr(vspace_id);256 257 // loop on the vobjs and get the ptpr258 for(vobj_id= vspace[vspace_id].vobj_offset;259 vobj_id < (vspace[vspace_id].vobj_offset+ vspace[vspace_id].vobjs);260 vobj_id++)261 {262 switch( vobj[vobj_id].type )263 {264 case VOBJ_TYPE_PTAB: // initialise page table pointers array265 {266 break;//already handled267 }268 case VOBJ_TYPE_MWMR: // storage capacity is (vobj.length/4 - 5) words269 {270 mwmr_channel_t* mwmr = (mwmr_channel_t*)(vobj[vobj_id].vaddr);271 mwmr->ptw = 0;272 mwmr->ptr = 0;273 mwmr->sts = 0;274 mwmr->depth = ((vobj[vobj_id].length>>2) - 6);//6= number of entry in the strucure275 mwmr->width = vobj[vobj_id].init;276 mwmr->lock = 0;277 #if INIT_DEBUG_CTX278 _puts("[INIT] MWMR channel ");279 _puts( vobj[vobj_id].name);280 _puts(" / depth = ");281 _putw( mwmr->depth );282 _puts("\n");283 #endif284 break;285 }286 case VOBJ_TYPE_ELF: // initialisation done by the loader287 {288 289 #if INIT_DEBUG_CTX290 _puts("[INIT] ELF section ");291 _puts( vobj[vobj_id].name);292 _puts(" / length = ");293 _putw( vobj[vobj_id].length );294 _puts("\n");295 #endif296 break;297 }298 case VOBJ_TYPE_BARRIER: // init is the number of participants299 {300 giet_barrier_t* barrier = (giet_barrier_t*)(vobj[vobj_id].vaddr);301 barrier->count = 0;302 barrier->init = vobj[vobj_id].init;303 #if INIT_DEBUG_CTX304 _puts(" BARRIER ");305 _puts( vobj[vobj_id].name);306 _puts(" / init_value = ");307 _putw( barrier->init );308 _puts("\n");309 #endif310 break;311 }312 case VOBJ_TYPE_LOCK: // init is "not taken"313 {314 unsigned int* lock = (unsigned int*)(vobj[vobj_id].vaddr);315 *lock = 0;316 #if INIT_DEBUG_CTX317 _puts(" LOCK ");318 _puts( vobj[vobj_id].name);319 _puts("\n");320 #endif321 break;322 }323 case VOBJ_TYPE_BUFFER: // nothing to do324 {325 326 #if INIT_DEBUG_CTX327 _puts(" BUFFER ");328 _puts( vobj[vobj_id].name);329 _puts(" / length = ");330 _putw( vobj[vobj_id].length );331 _puts("\n");332 #endif333 break;334 }335 default:336 {337 _puts("\n[INIT ERROR] illegal vobj of name ");338 _puts(vobj[vobj_id].name);339 _puts(" / in vspace = ");340 _puts(vobj[vobj_id].name);341 _puts("\n ");342 _exit();343 }344 } // end switch type345 } // end loop on vobjs346 } // end loop on vspaces347 348 _puts("\n[INIT] Vobjs initialisation completed at cycle : ");349 _putw( _proctime() );350 _puts("\n");351 352 } // end kernel_vobjs_init()353 354 ///////////////////////////////////////////////////////////////////////////////355 // This function maps a given task, defined in a given vspace356 // on the processor allocated in the mapping_info structure,357 // and initialises the task context.358 // There is one scheduler per processor, and processor can be shared359 // by several applications running in different vspaces.360 // There is one private context array handled by each scheduler.361 //362 // The following values must be initialised in all task contexts:363 // - sp stack pointer = stack_base + stack_length364 // - ra return address = &_eret365 // - epc start address = start_vector[task->startid]366 // - sr status register = OxFF13367 // - tty TTY terminal index (global index)368 // - fb FB_DMA channel index (global index)369 // - ptpr page table base address / 8K370 // - mode mmu_mode = 0xF (TLBs and caches activated)371 // - ptab page table virtual address372 ////////////////////////////////////////////////////////////////////////////////373 in_kinit void _task_map( unsigned int task_id, // global index374 unsigned int vspace_id, // global index375 unsigned int tty_id, // TTY index376 unsigned int fbdma_id ) // FBDMA index377 {378 mapping_header_t* header = (mapping_header_t*)&seg_mapping_base;379 380 mapping_task_t* task = _get_task_base(header);381 mapping_vspace_t* vspace = _get_vspace_base(header);382 mapping_vobj_t* vobj = _get_vobj_base( header );383 384 /** Set the current vspace ptpr before acessing the memory */385 _set_ptpr(vspace_id);386 387 // values to be initialised in task context388 unsigned int ra = (unsigned int)&_eret;389 unsigned int sr = 0x0000FF13;390 unsigned int tty = tty_id;391 unsigned int fb = fbdma_id;392 unsigned int ptpr = _kernel_ptabs_paddr[vspace_id] >> 13;393 unsigned int ptab = _kernel_ptabs_vaddr[vspace_id];394 unsigned int mode = 0xF;395 unsigned int sp;396 unsigned int epc;397 398 // EPC : Get the (virtual) base address of the start_vector containing399 // the start addresses for all tasks defined in a vspace.400 mapping_vobj_t* vobj_data = &vobj[vspace[vspace_id].vobj_offset +401 vspace[vspace_id].start_offset];402 unsigned int* start_vector = (unsigned int*)vobj_data->vaddr;403 epc = start_vector[task[task_id].startid];404 405 // SP : Get the vobj containing the stack406 unsigned int vobj_id = task[task_id].vobjlocid + vspace[vspace_id].vobj_offset;407 sp = vobj[vobj_id].vaddr + vobj[vobj_id].length;408 409 // compute global processor index410 unsigned int proc_id = task[task_id].clusterid * NB_PROCS + task[task_id].proclocid;411 412 // compute and check local task index413 unsigned int ltid = _scheduler[proc_id].tasks;414 if ( ltid >= GIET_NB_TASKS_MAX )415 {416 _puts("\n[INIT ERROR] : too much tasks allocated to processor ");417 _putw( proc_id );418 _puts("\n");419 _exit();420 }421 422 // update number of tasks allocated to scheduler423 _scheduler[proc_id].tasks = ltid + 1;424 425 // initializes the task context426 _scheduler[proc_id].context[ltid][CTX_SR_ID] = sr;427 _scheduler[proc_id].context[ltid][CTX_SP_ID] = sp;428 _scheduler[proc_id].context[ltid][CTX_RA_ID] = ra;429 _scheduler[proc_id].context[ltid][CTX_EPC_ID] = epc;430 _scheduler[proc_id].context[ltid][CTX_PTPR_ID] = ptpr;431 _scheduler[proc_id].context[ltid][CTX_MODE_ID] = mode;432 _scheduler[proc_id].context[ltid][CTX_TTY_ID] = tty;433 _scheduler[proc_id].context[ltid][CTX_FBDMA_ID] = fb;434 _scheduler[proc_id].context[ltid][CTX_PTAB_ID] = ptab;435 _scheduler[proc_id].context[ltid][CTX_TASK_ID] = task_id;436 437 #if INIT_DEBUG_CTX438 _puts("Task ");439 _puts( task[task_id].name );440 _puts(" allocated to processor ");441 _putw( proc_id );442 _puts(" / ltid = ");443 _putw( ltid );444 _puts("\n");445 446 _puts(" - SR = ");447 _putw( sr );448 _puts(" saved at ");449 _putw( (unsigned int)&_scheduler[proc_id].context[ltid][CTX_SR_ID] );450 _puts("\n");451 452 _puts(" - RA = ");453 _putw( ra );454 _puts(" saved at ");455 _putw( (unsigned int)&_scheduler[proc_id].context[ltid][CTX_RA_ID] );456 _puts("\n");457 458 _puts(" - SP = ");459 _putw( sp );460 _puts(" saved at ");461 _putw( (unsigned int)&_scheduler[proc_id].context[ltid][CTX_SP_ID] );462 _puts("\n");463 464 _puts(" - EPC = ");465 _putw( epc );466 _puts(" saved at ");467 _putw( (unsigned int)&_scheduler[proc_id].context[ltid][CTX_EPC_ID] );468 _puts("\n");469 470 _puts(" - PTPR = ");471 _putw( ptpr<<13 );472 _puts(" saved at ");473 _putw( (unsigned int)&_scheduler[proc_id].context[ltid][CTX_PTPR_ID] );474 _puts("\n");475 476 _puts(" - TTY = ");477 _putw( tty );478 _puts(" saved at ");479 _putw( (unsigned int)&_scheduler[proc_id].context[ltid][CTX_TTY_ID] );480 _puts("\n");481 482 _puts(" - FB = ");483 _putw( fb );484 _puts(" saved at ");485 _putw( (unsigned int)&_scheduler[proc_id].context[ltid][CTX_FBDMA_ID] );486 _puts("\n");487 488 _puts(" - PTAB = ");489 _putw( ptab );490 _puts(" saved at ");491 _putw( (unsigned int)&_scheduler[proc_id].context[ltid][CTX_PTAB_ID] );492 _puts("\n");493 #endif494 495 } // end _task_map()496 497 ///////////////////////////////////////////////////////////////////////////////498 // This function initialises all task contexts and processors schedulers.499 // It sets the default values for all schedulers (tasks <= 0, current <= 0).500 // Finally, it scan all tasks in all vspaces to initialise the schedulers,501 // and the tasks contexts, as defined in the mapping_info data structure.502 // A global TTY index and a global FB channel are allocated if required.503 // TTY[0] is reserved for the kernel.504 ///////////////////////////////////////////////////////////////////////////////505 in_kinit void _kernel_tasks_init()506 {507 mapping_header_t* header = (mapping_header_t*)&seg_mapping_base;508 mapping_cluster_t* cluster = _get_cluster_base( header );509 mapping_vspace_t* vspace = _get_vspace_base( header );510 mapping_task_t* task = _get_task_base( header );511 512 unsigned int base_tty_id = 1; // TTY index allocator513 unsigned int base_fb_id = 0; // FB channel index allocator514 515 unsigned int cluster_id;516 unsigned int proc_id;517 unsigned int vspace_id;518 unsigned int task_id;519 520 // initialise the schedulers (not done by the compiler)521 for ( cluster_id = 0 ; cluster_id < header->clusters ; cluster_id++ )522 {523 for ( proc_id = 0 ; proc_id < cluster[cluster_id].procs ; proc_id++ )524 {525 if ( proc_id >= NB_PROCS )526 {527 _puts("\n[INIT ERROR] The number of processors in cluster ");528 _putw( cluster_id );529 _puts(" is larger than NB_PROCS \n");530 _exit();531 }532 _scheduler[cluster_id*NB_PROCS+proc_id].tasks = 0;533 _scheduler[cluster_id*NB_PROCS+proc_id].current = 0;534 }535 }536 537 // loop on the virtual spaces538 for ( vspace_id = 0 ; vspace_id < header->vspaces ; vspace_id++ )539 {540 541 #if INIT_DEBUG_CTX542 _puts("\n[INIT] mapping tasks in vspace ");543 _puts(vspace[vspace_id].name);544 _puts("\n");545 #endif546 // loop on the tasks547 for ( task_id = vspace[vspace_id].task_offset ;548 task_id < (vspace[vspace_id].task_offset + vspace[vspace_id].tasks) ;549 task_id++ )550 {551 unsigned int tty_id = 0xFFFFFFFF;552 unsigned int fb_id = 0xFFFFFFFF;553 if ( task[task_id].use_tty )554 {555 tty_id = base_tty_id;556 base_tty_id++;557 }558 if ( task[task_id].use_fb )559 {560 fb_id = base_fb_id;561 base_fb_id++;562 }563 _task_map( task_id, // global task index564 vspace_id, // vspace index565 tty_id, // global tty index566 fb_id ); // global fbdma index567 } // end loop on tasks568 } // end oop on vspaces569 570 _puts("\n[INIT] Task Contexts initialisation completed at cycle ");571 _putw( _proctime() );572 _puts("\n");573 574 #if INIT_DEBUG_CTX575 for ( cluster_id = 0 ; cluster_id < header->clusters ; cluster_id++ )576 {577 _puts("\nCluster ");578 _putw( cluster_id );579 _puts("\n");580 for ( proc_id = 0 ; proc_id < cluster[cluster_id].procs ; proc_id++ )581 {582 unsigned int ltid; // local task index583 unsigned int gtid; // global task index584 unsigned int pid = cluster_id * NB_PROCS + proc_id;585 586 _puts(" - processor ");587 _putw( pid );588 _puts("\n");589 for ( ltid = 0 ; ltid < _scheduler[pid].tasks ; ltid++ )590 {591 gtid = _scheduler[pid].context[ltid][CTX_TASK_ID];592 _puts(" task : ");593 _puts( task[gtid].name );594 _puts("\n");595 }596 }597 }598 #endif599 600 } // end _kernel_task_init()601 602 ////////////////////////////////////////////////////////////////////////////////603 // This function intializes the external periherals such as the IOB component604 // (I/O bridge, containing the IOMMU, the IOC (external disk controller),605 // the NIC (external network controller), the FBDMA (frame buffer controller),606 ////////////////////////////////////////////////////////////////////////////////607 in_kinit void _kernel_peripherals_init()608 {609 /////////////////////610 // IOC peripheral611 // we simply activate the IOC interrupts...612 if ( NB_IOC )613 {614 unsigned int* ioc_address = (unsigned int*)&seg_ioc_base;615 ioc_address[BLOCK_DEVICE_IRQ_ENABLE] = 1;616 }617 618 /////////////////////619 // FBDMA peripheral620 // we simply activate the DMA interrupts...621 if ( NB_DMAS )622 {623 unsigned int* dma_address = (unsigned int*)&seg_dma_base;624 dma_address[DMA_IRQ_DISABLE] = 0;625 }626 627 /////////////////////628 // IOB peripheral629 // must be initialised in case of IOMMU630 if ( GIET_IOMMU_ACTIVE )631 {632 unsigned int* iob_address = (unsigned int*)&seg_iob_base;633 634 // define IPI address mapping the IOC interrupt ...TODO...635 636 // set IOMMU page table address637 iob_address[IOB_IOMMU_PTPR] = (unsigned int)(&_iommu_ptab);638 639 // activate IOMMU640 iob_address[IOB_IOMMU_ACTIVE] = 1;641 }642 643 _puts("\n[INIT] Peripherals initialisation completed at cycle ");644 _putw( _proctime() );645 _puts("\n");646 647 } // end _kernel_peripherals_init()648 649 ////////////////////////////////////////////////////////////////////////////////650 // This function intialises the interrupt vector, and initialises651 // the ICU mask registers for all processors in all clusters.652 // It strongly depends on the actual peripheral hardware wiring.653 // In this peculiar version, all clusters are identical,654 // the number of processors per cluster cannot be larger than 8.655 // Processor 0 handle all interrupts corresponding to TTYs, DMAs and IOC656 // (ICU inputs from from IRQ[8] to IRQ[31]). Only the 8 TIMER interrupts657 // (ICU iputs IRQ[0] to IRQ[7]), that are used for context switching658 // are distributed to the 8 processors.659 ////////////////////////////////////////////////////////////////////////////////660 in_kinit void _kernel_interrupt_vector_init()661 {662 mapping_header_t* header = (mapping_header_t*)&seg_mapping_base;663 mapping_cluster_t* cluster = _get_cluster_base( header );664 665 unsigned int cluster_id;666 unsigned int proc_id;667 668 // ICU mask values (up to 8 processors per cluster)669 unsigned int icu_mask[8] = { 0xFFFFFF01,670 0x00000002,671 0x00000004,672 0x00000008,673 0x00000010,674 0x00000020,675 0x00000040,676 0x00000080 };677 678 // initialise ICUs for each processor in each cluster679 for ( cluster_id = 0 ; cluster_id < header->clusters ; cluster_id++ )680 {681 for ( proc_id = 0 ; proc_id < cluster[cluster_id].procs ; proc_id++ )682 {683 _icu_write( cluster_id, proc_id, ICU_MASK_SET, icu_mask[proc_id] );684 }685 }686 687 // initialize Interrupt vector688 689 _interrupt_vector[0] = &_isr_switch;690 _interrupt_vector[1] = &_isr_switch;691 _interrupt_vector[2] = &_isr_switch;692 _interrupt_vector[3] = &_isr_switch;693 _interrupt_vector[4] = &_isr_switch;694 _interrupt_vector[5] = &_isr_switch;695 _interrupt_vector[6] = &_isr_switch;696 _interrupt_vector[7] = &_isr_switch;697 698 _interrupt_vector[8] = &_isr_dma_0;699 _interrupt_vector[9] = &_isr_dma_1;700 _interrupt_vector[10] = &_isr_dma_2;701 _interrupt_vector[11] = &_isr_dma_3;702 _interrupt_vector[12] = &_isr_dma_4;703 _interrupt_vector[13] = &_isr_dma_5;704 _interrupt_vector[14] = &_isr_dma_6;705 _interrupt_vector[15] = &_isr_dma_7;706 707 _interrupt_vector[16] = &_isr_tty_get_0;708 _interrupt_vector[17] = &_isr_tty_get_1;709 _interrupt_vector[18] = &_isr_tty_get_2;710 _interrupt_vector[19] = &_isr_tty_get_3;711 _interrupt_vector[20] = &_isr_tty_get_4;712 _interrupt_vector[21] = &_isr_tty_get_5;713 _interrupt_vector[22] = &_isr_tty_get_6;714 _interrupt_vector[23] = &_isr_tty_get_7;715 _interrupt_vector[24] = &_isr_tty_get_8;716 _interrupt_vector[25] = &_isr_tty_get_9;717 _interrupt_vector[26] = &_isr_tty_get_10;718 _interrupt_vector[27] = &_isr_tty_get_11;719 _interrupt_vector[28] = &_isr_tty_get_12;720 _interrupt_vector[29] = &_isr_tty_get_13;721 _interrupt_vector[30] = &_isr_tty_get_14;722 723 _interrupt_vector[31] = &_isr_ioc;724 725 _puts("\n[INIT] Interrupt vector initialisation completed at cycle ");726 _putw( _proctime() );727 _puts("\n");728 729 } // end _kernel_interrup_vector_init()
Note: See TracChangeset
for help on using the changeset viewer.