Changeset 199 for soft/giet_vm/sys/ctx_handler.c
- Timestamp:
- Aug 9, 2012, 2:38:06 PM (12 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
soft/giet_vm/sys/ctx_handler.c
r189 r199 1 /////////////////////////////////////////////////////////////////////////////////////// 1 ///////////////////////////////////////////////////////////////////////////////////////// 2 2 // File : ctx_handler.c 3 3 // Date : 01/04/2012 4 4 // Authors : alain greiner & joel porquet 5 5 // Copyright (c) UPMC-LIP6 6 /////////////////////////////////////////////////////////////////////////////////////// 6 ///////////////////////////////////////////////////////////////////////////////////////// 7 7 // The ctx_handler.h and ctx_handler.c files are part of the GIET-VM nano-kernel. 8 8 // This code is used to support context switch when several tasks are executing 9 9 // in time multiplexing on a single processor. 10 // The tasks must be statically allocated to a processor in the boot phase, and 11 // there is one private scheduler per processor. 12 // Each sheduler contains up to 15 task contexts. 13 /////////////////////////////////////////////////////////////////////////////////////// 10 // The tasks are statically allocated to a processor in the boot phase, and 11 // there is one private scheduler per processor. Each sheduler occupies 4K bytes, 12 // and contains up to 14 task contexts (task_id is from 0 to 13). 13 // The task context [14] is reserved for the "idle" task that does nothing, and 14 // is launched by the scheduler when there is no other runable task. 15 ///////////////////////////////////////////////////////////////////////////////////////// 14 16 15 17 #include <giet_config.h> … … 20 22 #include <sys_handler.h> 21 23 22 /////////////////////////////////////////////////////////////////////////////////////// 24 ///////////////////////////////////////////////////////////////////////////////////////// 23 25 // A task context is an array of 64 words = 256 bytes. 24 // It contains copies of processor registers (when the task is preempted), 25 // and some general informations associated to the task. 26 // It contains copies of processor registers (when the task is preempted): 27 // - GPR[i], generally stored in slot (i). $0, *26 & $27 are not saved. 28 // - HI & LO registers 29 // - CP0 registers: EPC, SR, CR, BVAR 30 // - CP2 registers : PTPR 31 // It contains some general informations associated to the task: 32 // - TTY : terminal global index 33 // - FBDMA : DMA channel global index 34 // - NIC : NIC channel global index 35 // - TIMER : Timer global index 36 // - PTAB : page table virtual base address 37 // - LTID : Task local index (in scheduler) 38 // - VSID : Virtual space index 39 // - RUN : Task state (0 => sleeping / 1 => runable ) 26 40 // 27 // - It contains GPR[i], generally stored in slot (i). $0, *26 & $27 are not saved. 28 // - It contains HI & LO registers. 29 // - It contains CP0 registers: EPC, SR, CR, SCHED 30 // - It contains CP2 registers : PTPR and MODE. 31 // - It contains TTY global index, the FBDMA global index, the virtual base 32 // address of the page table (PTAB), and the task global index (TASK). 33 // 34 // ctx[0]<- SR|ctx[8] <- $8 |ctx[16]<- $16|ctx[24]<- $24|ctx[32]<- EPC |ctx[40]<- TTY 35 // ctx[1]<- $1|ctx[9] <- $9 |ctx[17]<- $17|ctx[25]<- $25|ctx[33]<- CR |ctx[41]<- FBDMA 36 // ctx[2]<- $2|ctx[10]<- $10|ctx[18]<- $18|ctx[26]<- LO |ctx[34]<- *** |ctx[42]<- PTAB 37 // ctx[3]<- $3|ctx[11]<- $11|ctx[19]<- $19|ctx[27]<- HI |ctx[35]<- PTPR|ctx[43]<- TASK 38 // ctx[4]<- $4|ctx[12]<- $12|ctx[20]<- $20|ctx[28]<- $28|ctx[36]<- MODE|ctx[44]<- SCHED 39 // ctx[5]<- $5|ctx[13]<- $13|ctx[21]<- $21|ctx[29]<- SP |ctx[37]<- *** |ctx[45]<- TIMER 40 // ctx[6]<- $6|ctx[14]<- $14|ctx[22]<- $22|ctx[30]<- $30|ctx[38]<- *** |ctx[46]<- *** 41 // ctx[7]<- $7|ctx[15]<- $15|ctx[23]<- $23|ctx[31]<- RA |ctx[39]<- *** |ctx[47]<- *** 42 //////////////////////////////////////////////////////////////////////////////////////// 41 // ctx[0]<- ***|ctx[8] <- $8 |ctx[16]<- $16|ctx[24]<- $24|ctx[32]<- EPC |ctx[40]<- TTY 42 // ctx[1]<- $1 |ctx[9] <- $9 |ctx[17]<- $17|ctx[25]<- $25|ctx[33]<- CR |ctx[41]<- FBDMA 43 // ctx[2]<- $2 |ctx[10]<- $10|ctx[18]<- $18|ctx[26]<- LO |ctx[34]<- SR |ctx[42]<- NIC 44 // ctx[3]<- $3 |ctx[11]<- $11|ctx[19]<- $19|ctx[27]<- HI |ctx[35]<- BVAR |ctx[43]<- TIMER 45 // ctx[4]<- $4 |ctx[12]<- $12|ctx[20]<- $20|ctx[28]<- $28|ctx[36]<- *** |ctx[44]<- PTAB 46 // ctx[5]<- $5 |ctx[13]<- $13|ctx[21]<- $21|ctx[29]<- SP |ctx[37]<- *** |ctx[45]<- LTID 47 // ctx[6]<- $6 |ctx[14]<- $14|ctx[22]<- $22|ctx[30]<- $30|ctx[38]<- *** |ctx[46]<- VSID 48 // ctx[7]<- $7 |ctx[15]<- $15|ctx[23]<- $23|ctx[31]<- RA |ctx[39]<- PTPR |ctx[47]<- RUN 49 ////////////////////////////////////////////////////////////////////////////////////////// 43 50 44 51 extern void _task_switch(unsigned int*, unsigned int*); … … 47 54 // _ctx_switch() 48 55 // This function performs a context switch between the running task 49 // and another task, using a round-robin sheduling policy. 56 // and another task, using a round-robin sheduling policy between all 57 // tasks allocated to a given processor (static allocation). 58 // It selects the next runable task to resume execution. 59 // If the only runable task is the current task, return without context switch. 60 // If there is no runable task, the scheduler switch to the default "idle" task. 50 61 // 51 // I t desactivate the DTLB, to directly access the scheduler using52 // the physical address stored in register CP0_SCHED.53 // All the context switch procedure is executed with interrupts masked.54 // 55 // The return address contained in $31 is saved in the current task context56 // (in the ctx[31] slot), and the function actually returns to the address57 // contained in the ctx[31] slot of the next task context.62 // Implementation notes: 63 // - As we only have the scheduler physical address (in CP0_SCHED register), 64 // this function must use specific assess functions to access the scheduler. 65 // - All the context switch procedure is executed with interrupts masked. 66 // - The return address contained in $31 is saved in the current task context 67 // (in the ctx[31] slot), and the function actually returns to the address 68 // contained in the ctx[31] slot of the next task context. 58 69 ///////////////////////////////////////////////////////////////////////////////// 59 70 void _ctx_switch() 60 71 { 61 unsigned int tasks;62 unsigned int curr_task_id;63 unsigned int next_task_id;64 unsigned int *curr_ctx_paddr;65 unsigned int *next_ctx_paddr;66 67 72 // get scheduler physical address 68 73 static_scheduler_t* psched = (static_scheduler_t*)_get_sched(); 69 74 70 75 // get number of tasks allocated to scheduler 71 tasks = _get_tasks_number();76 unsigned int tasks = _get_tasks_number(); 72 77 73 // no switch if only one task 74 if ( tasks > 1) 78 // get current task index 79 unsigned int curr_task_id = _get_current_task_id(); 80 81 // select the next task using a round-robin policy 82 unsigned int next_task_id; 83 unsigned int tid; 84 unsigned int found = 0; 85 86 for ( tid = curr_task_id + 1 ; 87 tid < curr_task_id + 1 + tasks ; 88 tid++ ) 75 89 { 76 // compute the context physical address for the current task 77 curr_task_id = _get_current_task_id(); 78 curr_ctx_paddr = &(psched->context[curr_task_id][0]); 79 80 // select the next task using a round-robin policy 81 next_task_id = (curr_task_id + 1) % tasks; 82 83 // compute the context physical address for the next task 84 next_ctx_paddr = &(psched->context[next_task_id][0]); 90 next_task_id = tid % tasks; 85 91 86 // update the scheduler state 92 // test if the task is runable 93 if ( _get_context_slot( next_task_id, CTX_RUN_ID ) ) 94 { 95 found = 1; 96 break; 97 } 98 } 99 100 // launch "idle" task if no runable task 101 if ( found == 0 ) 102 { 103 next_task_id = IDLE_TASK_INDEX; 104 } 105 106 // no switch if no change 107 if ( curr_task_id != next_task_id ) 108 { 109 unsigned int* curr_ctx_paddr = &(psched->context[curr_task_id][0]); 110 unsigned int* next_ctx_paddr = &(psched->context[next_task_id][0]); 111 87 112 _set_current_task_id( next_task_id ); 113 _task_switch( curr_ctx_paddr, next_ctx_paddr ); 88 114 89 115 #if GIET_DEBUG_SWITCH 90 116 _get_lock( &_tty_put_lock ); 91 _puts( "\n[GIET ] Context switch for processor ");92 _put w( _procid() );117 _puts( "\n[GIET DEBUG] Context switch for processor "); 118 _putd( _procid() ); 93 119 _puts( " at cycle "); 94 _put w( _proctime() );120 _putd( _proctime() ); 95 121 _puts("\n"); 96 122 _puts( " - tasks = "); 97 _put w( tasks );123 _putd( tasks ); 98 124 _puts("\n"); 99 125 _puts( " - curr_task_id = "); 100 _put w( curr_task_id );126 _putd( curr_task_id ); 101 127 _puts("\n"); 102 128 _puts( " - next_task_id = "); 103 _put w( next_task_id );129 _putd( next_task_id ); 104 130 _puts("\n"); 105 131 _release_lock( &_tty_put_lock ); 106 132 #endif 107 133 108 // makes the task switch109 _task_switch( curr_ctx_paddr, next_ctx_paddr ); 134 } 135 } //end _ctx_switch() 110 136 111 /* 112 asm volatile( "ori $27, $0, 0xB \n" 113 "mtc2 $27, $1 \n" // desactivate DTLB 137 ///////////////////////////////////////////////////////////////////////////////////// 138 // This function is executed as the"idle" task when no other task can be executed 139 ///////////////////////////////////////////////////////////////////////////////////// 140 void _ctx_idle() 141 { 142 unsigned int delay = 1000000; 114 143 115 "add $27, %0, $0 \n" // $27 <= &curr_ctx 144 while(1) 145 { 146 asm volatile("move $3, %0 \n" 147 "loop: \n" 148 "addi $3, $3, -1 \n" 149 "bnez $3, loop \n" 150 "nop \n" 151 : 152 : "r"(delay) 153 : "$3" ); 116 154 117 "mfc0 $26, $12 \n" // $26 <= SR 118 "sw $26, 0*4($27) \n" // ctx[0] <= SR 119 ".set noat \n" 120 "sw $1, 1*4($27) \n" // ctx[1] <= $1 121 ".set at \n" 122 "sw $2, 2*4($27) \n" // ctx[2] <= $2 123 "sw $3, 3*4($27) \n" // ctx[3] <= $3 124 "sw $4, 4*4($27) \n" // ctx[4] <= $4 125 "sw $5, 5*4($27) \n" // ctx[5] <= $5 126 "sw $6, 6*4($27) \n" // ctx[6] <= $6 127 "sw $7, 7*4($27) \n" // ctx[7] <= $7 128 "sw $8, 8*4($27) \n" // ctx[8] <= $8 129 "sw $9, 9*4($27) \n" // ctx[9] <= $9 130 "sw $10, 10*4($27) \n" // ctx[10] <= $10 131 "sw $11, 11*4($27) \n" // ctx[11] <= $11 132 "sw $12, 12*4($27) \n" // ctx[12] <= $12 133 "sw $13, 13*4($27) \n" // ctx[13] <= $13 134 "sw $14, 14*4($27) \n" // ctx[14] <= $14 135 "sw $15, 15*4($27) \n" // ctx[15] <= $15 136 "sw $16, 16*4($27) \n" // ctx[16] <= $16 137 "sw $17, 17*4($27) \n" // ctx[17] <= $17 138 "sw $18, 18*4($27) \n" // ctx[18] <= $18 139 "sw $19, 19*4($27) \n" // ctx[19] <= $19 140 "sw $20, 20*4($27) \n" // ctx[20] <= $20 141 "sw $21, 21*4($27) \n" // ctx[21] <= $21 142 "sw $22, 22*4($27) \n" // ctx[22] <= $22 143 "sw $23, 23*4($27) \n" // ctx[23] <= $23 144 "sw $24, 24*4($27) \n" // ctx[24] <= $24 145 "sw $25, 25*4($27) \n" // ctx[25] <= $25 146 "mflo $26 \n" 147 "sw $26, 26*4($27) \n" // ctx[26] <= LO 148 "mfhi $26 \n" 149 "sw $26, 27*4($27) \n" // ctx[27] <= H1 150 "sw $28, 28*4($27) \n" // ctx[28] <= $28 151 "sw $29, 29*4($27) \n" // ctx[29] <= $29 152 "sw $30, 30*4($27) \n" // ctx[30] <= $30 153 "sw $31, 31*4($27) \n" // ctx[31] <= $31 154 "mfc0 $26, $14 \n" 155 "sw $26, 32*4($27) \n" // ctx[32] <= EPC 156 "mfc0 $26, $13 \n" 157 "sw $26, 33*4($27) \n" // ctx[33] <= CR 158 "mfc2 $26, $0 \n" 159 "sw $26, 35*4($27) \n" // ctx[35] <= PTPR 155 _get_lock( &_tty_put_lock ); 156 _puts( "\n[GIET WARNING] Processor "); 157 _putd( _procid() ); 158 _puts( " still idle at cycle "); 159 _putd( _proctime() ); 160 _puts("\n"); 161 _release_lock( &_tty_put_lock ); 162 163 } 164 } // end ctx_idle() 160 165 161 "add $27, %1, $0 \n" // $27<= &next_ctx 166 ///////////////////////////////////////////////////////////////////////////////// 167 // The address of this functionis used to initialise the return address 168 // in the "idle" task context. 169 ///////////////////////////////////////////////////////////////////////////////// 170 void _ctx_eret() 171 { 172 asm volatile("eret"); 173 } 162 174 163 "lw $26, 35*4($27) \n"164 "mtc2 $26, $0 \n" // restore PTPR165 "lw $26, 0*4($27) \n"166 "mtc0 $26, $12 \n" // restore SR167 ".set noat \n"168 "lw $1, 1*4($27) \n" // restore $1169 ".set at \n"170 "lw $2, 2*4($27) \n" // restore $2171 "lw $3, 3*4($27) \n" // restore $3172 "lw $4, 4*4($27) \n" // restore $4173 "lw $5, 5*4($27) \n" // restore $5174 "lw $6, 6*4($27) \n" // restore $6175 "lw $7, 7*4($27) \n" // restore $7176 "lw $8, 8*4($27) \n" // restore $8177 "lw $9, 9*4($27) \n" // restore $9178 "lw $10, 10*4($27) \n" // restore $10179 "lw $11, 11*4($27) \n" // restore $11180 "lw $12, 12*4($27) \n" // restore $12181 "lw $13, 13*4($27) \n" // restore $13182 "lw $14, 14*4($27) \n" // restore $14183 "lw $15, 15*4($27) \n" // restore $15184 "lw $16, 16*4($27) \n" // restore $16185 "lw $17, 17*4($27) \n" // restore $17186 "lw $18, 18*4($27) \n" // restore $18187 "lw $19, 19*4($27) \n" // restore $19188 "lw $20, 20*4($27) \n" // restore $20189 "lw $21, 21*4($27) \n" // restore $21190 "lw $22, 22*4($27) \n" // restore $22191 "lw $23, 23*4($27) \n" // restore $23192 "lw $24, 24*4($27) \n" // restore $24193 "lw $25, 25*4($27) \n" // restore $25194 "lw $26, 26*4($27) \n"195 "mtlo $26 \n" // restore LO196 "lw $26, 27*4($27) \n"197 "mthi $26 \n" // restore HI198 "lw $28, 28*4($27) \n" // restore $28199 "lw $29, 29*4($27) \n" // restore $29200 "lw $30, 30*4($27) \n" // restore $30201 "lw $31, 31*4($27) \n" // restore $31202 "lw $26, 32*4($27) \n"203 "mtc0 $26, $14 \n" // restore EPC204 "lw $26, 33*4($27) \n"205 "mtc0 $26, $13 \n" // restore CR206 175 207 "ori $27, $0, 0xF \n"208 "mtc2 $27, $1 \n" // activate DTLB209 :210 : "r"(curr_ctx_paddr), "r"(next_ctx_paddr)211 : "$1" , "$4" ,"$5" ,"$6" ,"$7" ,"$8" ,"$9" ,"$10",212 "$11","$12","$13","$14","$15","$16","$17","$18","$19","$20",213 "$21","$22","$23","$24","$25","$26","$27", "$29",214 "$31" );215 */216 }217 } // end _ctx_switch218
Note: See TracChangeset
for help on using the changeset viewer.