Changeset 294 for soft/giet_vm/giet_kernel/kernel_init.c
- Timestamp:
- Mar 26, 2014, 6:10:01 PM (11 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
soft/giet_vm/giet_kernel/kernel_init.c
r293 r294 61 61 62 62 __attribute__((section (".kdata"))) 63 static_scheduler_t* _schedulers[NB_PROCS_MAX<<(X_WIDTH+Y_WIDTH)]; 63 static_scheduler_t* _schedulers[NB_PROCS_MAX<<(X_WIDTH+Y_WIDTH)]; // virtual addresses 64 64 65 65 //////////////////////////////////////////////////////////////////////////////////// … … 69 69 __attribute__((section (".kdata"))) 70 70 unsigned int _idle_stack[X_SIZE * Y_SIZE * NB_PROCS_MAX * 128 ]; 71 72 //////////////////////////////////////////////////////////////////////////////////// 73 // Synchonisation Barrier before jumping to user code 74 //////////////////////////////////////////////////////////////////////////////////// 75 76 __attribute__((section (".kdata"))) 77 unsigned int _init_barrier = 0; 71 78 72 79 //////////////////////////////////////////////////////////////////////////////////// … … 99 106 // 1/ contribute to _schedulers_paddr[] array initialisation. 100 107 // 2/ contribute to _ptabs_paddr[] and _ptabs_vaddr arrays initialisation 101 // 3/ comp ute and set the ICU mask for its private ICU channel102 // 4/ initialise its private TICK timer (if tasks > 0)103 // 5/ initialise the "idle" task context in its private scheduler104 // 6/ initialise the SP, SR, PTPR, EPC registers105 // 7/ jump to theuser code with an eret.108 // 3/ completes task context initialisation for ech allocated task 109 // 4/ compute and set the ICU mask for its private ICU channel 110 // 5/ initialise its private TICK timer (if tasks > 0) 111 // 6/ initialise the "idle" task context in its private scheduler 112 // 7/ initialise SP, SR, PTPR, EPC registers and jump to user code with an eret. 106 113 //////////////////////////////////////////////////////////////////////////////////// 107 114 __attribute__((section (".kinit"))) void kernel_parallel_init() … … 109 116 unsigned int global_pid = _get_procid(); 110 117 unsigned int cluster_xy = global_pid / NB_PROCS_MAX; 111 unsigned int local_pid = global_pid % NB_PROCS_MAX; 112 113 #if 0 114 ////////////// Debug : we can kill all processors but one 115 if ( global_pid != 0 ) 116 { 117 _tty_get_lock( 0 ); 118 _puts("\n[GIET] Processor["); 119 _putd( cluster_xy >> Y_WIDTH ); 120 _puts(","); 121 _putd( cluster_xy & ((1<<Y_WIDTH)-1) ); 122 _puts(","); 123 _putd( local_pid ); 124 _puts("] suicide...\n"); 125 _tty_release_lock( 0 ); 126 _exit(); 127 } 128 #endif 118 unsigned int x = cluster_xy >> Y_WIDTH; 119 unsigned int y = cluster_xy & ((1<<Y_WIDTH)-1); 120 unsigned int lpid = global_pid % NB_PROCS_MAX; 129 121 130 122 // Step 1 : each processor get its scheduler virtual address … … 137 129 138 130 #if GIET_DEBUG_INIT 139 _tty_get_lock( 0 ); 140 _puts("\n[GIET DEBUG] Parallel init : step 1 for processor["); 141 _putd( cluster_xy >> Y_WIDTH ); 142 _puts(","); 143 _putd( cluster_xy & ((1<<Y_WIDTH)-1) ); 144 _puts(","); 145 _putd( local_pid ); 146 _puts("]\n - scheduler vbase = "); 147 _putx((unsigned int) psched); 148 _puts("\n - tasks = "); 149 _putd(tasks); 150 _puts("\n"); 151 _tty_release_lock( 0 ); 152 #endif 153 154 // step 2 : each processor that is allocated at least one task 155 // completes its private scheduler initialisation, and 156 // contribute to _ptabs_vaddr[] and _ptabs_ptprs[] arrays initialisation. 157 // - set the CTX_RA slot vith the virtual address 158 // of the _ctx_eret() function (for context switch). 159 // - set the CTX_EPC slot that must contain the task 160 // entry point, and contain only the address of the 161 // memory location containing this entry point. 131 _printf("\n[GIET DEBUG INIT] Processor[%d,%d,%d]\n" 132 " - scheduler vbase = %x\n" 133 " - tasks = %d\n", 134 x, y, lpid, (unsigned int)psched, tasks ); 135 #endif 136 137 // step 2 : each processor that is allocated at least one task loops 138 // on all allocated tasks: 139 // - contributes to _ptabs_vaddr[] & _ptabs_ptprs[] initialisation. 140 // - set CTX_RA slot with the kernel _ctx_eret() virtual address. 141 // - set CTX_EPC slot that must contain the task entry point, 142 // and contain only at this point the virtual address of the memory 143 // location containing this entry point. We must switch the PTPR 144 // to use the page table corresponding to the task. 162 145 163 146 unsigned int ltid; 164 147 165 // loop on all allocated tasks166 148 for (ltid = 0; ltid < tasks; ltid++) 167 149 { … … 170 152 unsigned int ptpr = _get_task_slot( global_pid, ltid , CTX_PTPR_ID ); 171 153 154 // initialize PTABS arrays 172 155 _ptabs_vaddr[vsid] = ptab; 173 156 _ptabs_ptprs[vsid] = ptpr; 174 157 158 #if GIET_DEBUG_INIT 159 _printf("\n[GIET DEBUG INIT] Processor[%d,%d,%d] contibutes to PTABS arrays\n" 160 " - ptabs_vaddr[%d] = %x / ptpr_paddr[%d] = %l\n", 161 x, y, lpid, 162 vsid, ptab, vsid, ((unsigned long long)ptpr)<<13 ); 163 #endif 164 165 // set the ptpr to use the task page table 166 asm volatile( "mtc2 %0, $0 \n" 167 : : "r" (ptpr) ); 168 169 // compute ctx_ra 175 170 unsigned int ctx_ra = (unsigned int)(&_ctx_eret); 176 171 _set_task_slot( global_pid, ltid, CTX_RA_ID, ctx_ra ); 177 172 173 // compute ctx_epc 178 174 unsigned int* ptr = (unsigned int*)_get_task_slot( global_pid, ltid, CTX_EPC_ID ); 179 175 _set_task_slot( global_pid, ltid, CTX_EPC_ID, *ptr ); 180 176 181 177 #if GIET_DEBUG_INIT 182 _tty_get_lock( 0 ); 183 _puts("\n[GIET DEBUG] Parallel init : step 2 for processor["); 184 _putd( cluster_xy >> Y_WIDTH ); 185 _puts(","); 186 _putd( cluster_xy & ((1<<Y_WIDTH)-1) ); 187 _puts(","); 188 _putd( local_pid ); 189 _puts("] / task "); 190 _putd( ltid ); 191 _puts("\n - ctx_vsid = "); 192 _putd( _get_task_slot( global_pid, ltid, CTX_VSID_ID ) ); 193 _puts("\n - ctx_ptpr = "); 194 _putx( _get_task_slot( global_pid, ltid, CTX_PTPR_ID ) ); 195 _puts("\n - ctx_ptab = "); 196 _putx( _get_task_slot( global_pid, ltid, CTX_PTAB_ID ) ); 197 _puts("\n - ctx_ltid = "); 198 _putd( _get_task_slot( global_pid, ltid, CTX_LTID_ID ) ); 199 _puts("\n - ctx_epc = "); 200 _putx( _get_task_slot( global_pid, ltid, CTX_EPC_ID ) ); 201 _puts("\n - ctx_ra = "); 202 _putx( _get_task_slot( global_pid, ltid, CTX_RA_ID ) ); 203 _puts("\n - ctx_gtid = "); 204 _putd( _get_task_slot( global_pid, ltid, CTX_GTID_ID ) ); 205 _puts("\n - ctx_tty = "); 206 _putd( _get_task_slot( global_pid, ltid, CTX_TTY_ID ) ); 207 _puts("\n"); 208 _tty_release_lock( 0 ); 209 #endif 210 178 _printf("\n[GIET DEBUG INIT] Processor[%d,%d,%d] set scheduler for task %d\n" 179 " - ctx_epc = %x\n" 180 " - ctx_ra = %x\n", 181 x, y, lpid, ltid, 182 _get_task_slot( global_pid, ltid, CTX_EPC_ID ), 183 _get_task_slot( global_pid, ltid, CTX_RA_ID ) ); 184 #endif 185 186 } // end for tasks 187 188 // step 4 : compute and set ICU or XCU masks 189 190 unsigned int isr_switch_index = 0xFFFFFFFF; 191 unsigned int hwi_mask = 0; 192 unsigned int pti_mask = 0; 193 unsigned int wti_mask = 0; 194 unsigned int irq_id; // IN_IRQ index 195 unsigned int entry; // interrupt vector entry 196 197 for (irq_id = 0; irq_id < 32; irq_id++) 198 { 199 entry = psched->hwi_vector[irq_id]; 200 if ( entry & 0x80000000 ) hwi_mask = hwi_mask | (1<<irq_id); 201 if ( (entry & 0x0000FFFF) == ISR_TICK ) isr_switch_index = irq_id; 202 203 entry = psched->pti_vector[irq_id]; 204 if ( entry & 0x80000000 ) pti_mask = pti_mask | (1<<irq_id); 205 if ( (entry & 0x0000FFFF) == ISR_TICK ) isr_switch_index = irq_id; 206 207 entry = psched->wti_vector[irq_id]; 208 if ( entry & 0x80000000 ) wti_mask = wti_mask | (1<<irq_id); 209 if ( (entry & 0x0000FFFF) == ISR_TICK ) isr_switch_index = irq_id; 211 210 } 212 211 213 // step 3 : compute and set ICU or XICU masks 214 // there is at most 32 interrupts per processor 215 216 unsigned int isr_switch_index = 0xFFFFFFFF; 217 unsigned int irq_id; // IN_IRQ index 218 unsigned int hwi_mask = 0; 219 unsigned int swi_mask = 0; 220 unsigned int pti_mask = 0; 221 222 for (irq_id = 0; irq_id < 32; irq_id++) 223 { 224 unsigned int entry = psched->interrupt_vector[irq_id]; 225 unsigned int isr = (entry & 0x000000FF); 226 unsigned int type = (entry & 0x0000FF00) >> 8; 227 unsigned int valid = (entry & 0x80000000); 228 229 if ((type == IRQ_TYPE_HWI) && valid ) hwi_mask = hwi_mask | (1<<irq_id); 230 else if ((type == IRQ_TYPE_SWI) && valid ) swi_mask = swi_mask | (1<<irq_id); 231 else if ((type == IRQ_TYPE_PTI) && valid ) pti_mask = pti_mask | (1<<irq_id); 232 else if ( valid ) 212 #if GIET_DEBUG_INIT 213 _printf("\n[GIET DEBUG INIT] Processor[%d,%d,%d] set XCU masks\n" 214 " - ICU HWI_MASK = %x\n" 215 " - ICU WTI_MASK = %x\n" 216 " - ICU PTI_MASK = %x\n", 217 x, y, lpid, hwi_mask, wti_mask, pti_mask ); 218 #endif 219 220 unsigned int channel = lpid * IRQ_PER_PROCESSOR; 221 222 #if USE_XICU 223 _xcu_set_mask( cluster_xy, channel, hwi_mask, IRQ_TYPE_HWI ); 224 _xcu_set_mask( cluster_xy, channel, wti_mask, IRQ_TYPE_WTI ); 225 _xcu_set_mask( cluster_xy, channel, pti_mask, IRQ_TYPE_PTI ); 226 #else 227 _icu_set_mask( cluster_xy, channel, hwi_mask ); 228 #endif 229 230 // step 5 : start TICK timer if at least one task 231 if (tasks > 0) 232 { 233 // one ISR_TICK must be defined for each proc 234 if (isr_switch_index == 0xFFFFFFFF) 233 235 { 234 _puts("\n[GIET ERROR] _kernel_parallel_start() : illegal IRQ type\n"); 235 _puts(" irq_id = "); 236 _putx( irq_id ); 237 _puts(" / entry = "); 238 _putx( entry ); 239 _puts("\n"); 236 _printf("\n[GIET ERROR] ISR_TICK not found for processor[%d,%d,%d]\n", 237 x, y, lpid ); 240 238 _exit(); 241 239 } 242 if (isr == ISR_SWITCH) isr_switch_index = irq_id; 240 241 // start system timer 242 243 #if USE_XICU 244 _xcu_timer_start( cluster_xy, isr_switch_index, GIET_TICK_VALUE ); 245 #else 246 _timer_start( cluster_xy, isr_switch_index, GIET_TICK_VALUE ); 247 #endif 248 243 249 } 244 250 245 251 #if GIET_DEBUG_INIT 246 _tty_get_lock( 0 ); 247 _puts("\n[GIET DEBUG] Parallel init : step 3 for processor["); 248 _putd( cluster_xy >> Y_WIDTH ); 249 _puts(","); 250 _putd( cluster_xy & ((1<<Y_WIDTH)-1) ); 251 _puts(","); 252 _putd( local_pid ); 253 _puts("]\n - ICU HWI_MASK = "); 254 _putx(hwi_mask); 255 _puts("\n - ICU SWI_MASK = "); 256 _putx(swi_mask); 257 _puts("\n - ICU PTI_MASK = "); 258 _putx(pti_mask); 259 _puts("\n"); 260 _tty_release_lock( 0 ); 261 #endif 262 263 // GIET-VM constraint : only one IRQ type per irq_id 264 if ( hwi_mask & swi_mask & pti_mask ) 265 { 266 _puts("[GIET ERROR] _kernel_parallel_start : conflicting IRQs\n"); 267 _exit(); 268 } 269 270 271 // The ICU output index is computed as the local processor id multiplied by 272 // the number of ICU outputs connected to each processor. 273 int icu_out_index = local_pid * IRQ_PER_PROCESSOR; 274 275 #if USE_XICU 276 _xcu_set_mask(cluster_xy, icu_out_index, hwi_mask, IRQ_TYPE_HWI); // set HWI_MASK 277 _xcu_set_mask(cluster_xy, icu_out_index, swi_mask, IRQ_TYPE_SWI); // set SWI_MASK 278 _xcu_set_mask(cluster_xy, icu_out_index, pti_mask, IRQ_TYPE_PTI); // set PTI_MASK 279 #else 280 _icu_set_mask(cluster_xy, icu_out_index, (hwi_mask | pti_mask | swi_mask) ); 281 #endif 282 283 // step 4 : start TICK timer if at least one task 284 if (tasks > 0) 285 { 286 // one ISR_SWITCH must be defined for each proc 287 if (isr_switch_index == 0xFFFFFFFF) 288 { 289 _tty_get_lock( 0 ); 290 _puts("\n[GIET ERROR] ISR_SWITCH not found for processor "); 291 _putx(global_pid); 292 _puts("\n"); 293 _tty_release_lock( 0 ); 294 _exit(); 295 } 296 297 // the ISR_SWITCH irq index must be NB_PROCS_MAX + local_pid because 298 // the first NB_PROCS_MAX irqs are used by the WAKEUP ones 299 if (isr_switch_index != (NB_PROCS_MAX + local_pid)) 300 { 301 _tty_get_lock( 0 ); 302 _puts("\n[GIET ERROR] ISR_SWITCH wrong index for processor "); 303 _putx(global_pid); 304 _puts("\n. It should be NB_PROCS_MAX + local_pid ="); 305 _putd(NB_PROCS_MAX + local_pid); 306 _puts("\n"); 307 _tty_release_lock( 0 ); 308 _exit(); 309 } 310 311 // start system timer 312 unsigned int ko; 313 #if USE_XICU 314 ko = _xcu_timer_start( cluster_xy, isr_switch_index, GIET_TICK_VALUE ); 315 #else 316 ko = _timer_start( cluster_xy, isr_switch_index, GIET_TICK_VALUE ); 317 #endif 318 if ( ko ) 319 { 320 _tty_get_lock( 0 ); 321 _puts("\n[GIET ERROR] cannot start timer for processor "); 322 _putd(local_pid); 323 _puts("\n"); 324 _tty_release_lock( 0 ); 325 _exit(); 326 } 327 } 328 329 #if GIET_DEBUG_INIT 330 _tty_get_lock( 0 ); 331 _puts("\n[GIET DEBUG] Parallel init : step 4 for processor["); 332 _putd( cluster_xy >> Y_WIDTH ); 333 _puts(","); 334 _putd( cluster_xy & ((1<<Y_WIDTH)-1) ); 335 _puts(","); 336 _putd( local_pid ); 337 _puts("]"); 338 if ( tasks > 1 ) _puts("\n context switch activated\n"); 339 else _puts("\n context switch not activated\n"); 340 _tty_release_lock( 0 ); 341 #endif 342 343 // step 5 : each processor updates the idle_task context: 252 _printf("\n[GIET DEBUG INIT] Processor[%d,%d,%d] start TICK timer\n", 253 x, y, lpid ); 254 #endif 255 256 // step 6 : each processor updates the idle_task context: 344 257 // (only CTX_SP, CTX_RA, CTX_EPC). 345 258 // The stack size is 512 bytes, reserved in seg_kdata. … … 347 260 // have been initialised in boot code. 348 261 349 unsigned int x = cluster_xy >> Y_WIDTH; 350 unsigned int y = cluster_xy & ((1<<Y_WIDTH)-1); 351 unsigned int p = ((x * Y_SIZE) + y) * NB_PROCS_MAX + local_pid; 262 unsigned int p = ((x * Y_SIZE) + y) * NB_PROCS_MAX + lpid; 352 263 353 264 unsigned int stack = (unsigned int)_idle_stack + ((p + 1)<<9); … … 358 269 359 270 #if GIET_DEBUG_INIT 360 _tty_get_lock( 0 ); 361 _puts("\n[GIET DEBUG] Parallel init : step 5 for processor["); 362 _putd( cluster_xy >> Y_WIDTH ); 363 _puts(","); 364 _putd( cluster_xy & ((1<<Y_WIDTH)-1) ); 365 _puts(","); 366 _putd( local_pid ); 367 _puts("] : idle task context set\n"); 368 _tty_release_lock( 0 ); 369 #endif 370 371 // step 6 : each processor initialises SP, SR, PTPR, EPC, registers 271 _printf("\n[GIET DEBUG INIT] Processor[%d,%d,%d] initialize IDLE task\n", 272 x, y, lpid ); 273 #endif 274 275 // step 7 : when all processors reach the synchronisation barrier, 276 // each processor set registers SP, SR, PTPR, EPC, 372 277 // with the values corresponding to the first allocated task, 373 // or to the idle_task if there is no task allocated. 374 375 ltid = 0; 278 // or to the idle_task if there is no task allocated, 279 // and jump to user code 376 280 377 281 if (tasks == 0) … … 379 283 ltid = IDLE_TASK_INDEX; 380 284 381 _tty_get_lock( 0 ); 382 _puts("\n[GIET WARNING] No task allocated to processor "); 383 _putx(global_pid); 384 _puts(" => idle\n"); 385 _tty_release_lock ( 0 ); 285 _printf("\n[GIET WARNING] No task allocated to processor[%d,%d,%d]\n", 286 x, y, lpid ); 287 } 288 else 289 { 290 ltid = 0; 386 291 } 387 292 … … 392 297 393 298 #if GIET_DEBUG_INIT 394 _tty_get_lock( 0 ); 395 _puts("\n[GIET DEBUG] Parallel init : step 6 for processor["); 396 _putd( cluster_xy >> Y_WIDTH ); 397 _puts(","); 398 _putd( cluster_xy & ((1<<Y_WIDTH)-1) ); 399 _puts(","); 400 _putd( local_pid ); 401 _puts("]\n - sp = "); 402 _putx(sp_value); 403 _puts("\n - sr = "); 404 _putx(sr_value); 405 _puts("\n - ptpr = "); 406 _putx(ptpr_value); 407 _puts("\n - epc = "); 408 _putx(epc_value); 409 _puts("\n"); 410 411 _puts("\n[GIET DEBUG] Processor["); 412 _putd( cluster_xy >> Y_WIDTH ); 413 _puts(","); 414 _putd( cluster_xy & ((1<<Y_WIDTH)-1) ); 415 _puts(","); 416 _putd( local_pid ); 417 _puts("] completes kernel init at cycle "); 418 _putd( _get_proctime() ); 419 _puts(" / task_entry_point = "); 420 _putx( epc_value ); 421 _puts("\n"); 422 _tty_release_lock( 0 ); 423 #endif 424 425 // Step 7 : set registers and jump to user code 426 asm volatile ( 427 "move $29, %0 \n" /* SP <= ctx[CTX_SP_ID] */ 428 "mtc0 %1, $12 \n" /* SR <= ctx[CTX_SR_ID] */ 429 "mtc2 %2, $0 \n" /* PTPR <= ctx[CTX_PTPR_ID] */ 430 "mtc0 %3, $14 \n" /* EPC <= ctx[CTX_EPC_ID] */ 431 "eret \n" /* jump to user code */ 432 "nop \n" 433 : 434 : "r" (sp_value), "r" (sr_value), "r" (ptpr_value), "r" (epc_value)); 299 _printf("\n[GIET DEBUG INIT] Processor[%d,%d,%d] reach barrier at cycle %d\n" 300 " - sp = %x\n" 301 " - sr = %x\n" 302 " - ptpr = %x\n" 303 " - epc = %x\n", 304 x, y, lpid, _get_proctime(), 305 sp_value, sr_value, ptpr_value, epc_value ); 306 #endif 307 308 unsigned int* pcount = &_init_barrier; 309 unsigned int nprocs = X_SIZE*(Y_SIZE-1)*NB_PROCS_MAX; 310 unsigned int count; 311 312 // increment barrier counter with atomic LL/SC 313 asm volatile ( "_init_barrier_loop: \n" 314 "ll %0, 0(%1) \n" /* count <= *pcount */ 315 "addi $3, %0, 1 \n" /* $3 <= count + 1 */ 316 "sc $3, 0(%1) \n" /* *pcount <= $3 */ 317 "beqz $3, _init_barrier_loop \n" /* retry if failure */ 318 "nop \n" 319 : "=&r"(count) 320 : "r"(pcount) 321 : "$3" ); 322 323 // busy waiting until all processors synchronized 324 while ( *pcount != nprocs ) asm volatile ("nop"); 325 326 _printf("\n[GIET] Processor[%d,%d,%d] jumps to user code at cycle %d\n", 327 x, y, lpid, _get_proctime() ); 328 329 // set registers and jump to user code 330 asm volatile ( "move $29, %0 \n" /* SP <= ctx[CTX_SP_ID] */ 331 "mtc0 %1, $12 \n" /* SR <= ctx[CTX_SR_ID] */ 332 "mtc2 %2, $0 \n" /* PTPR <= ctx[CTX_PTPR] */ 333 "mtc0 %3, $14 \n" /* EPC <= ctx[CTX_EPC] */ 334 "eret \n" /* jump to user code */ 335 "nop \n" 336 : 337 : "r"(sp_value), "r"(sr_value), "r"(ptpr_value), "r"(epc_value) 338 : "$29" ); 435 339 436 340 } // end kernel_parallel_init()
Note: See TracChangeset
for help on using the changeset viewer.