Changeset 294
- Timestamp:
- Mar 26, 2014, 6:10:01 PM (11 years ago)
- Location:
- soft/giet_vm/giet_kernel
- Files:
-
- 8 edited
Legend:
- Unmodified
- Added
- Removed
-
soft/giet_vm/giet_kernel/ctx_handler.c
r275 r294 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 ///////////////////////////////////////////////////////////////////////////////////////// 7 // The ctx_handler.h and ctx_handler.c files are part of the GIET-VM nano-kernel. 8 // This code is used to support context switch when several tasks are executing 9 // in time multiplexing on a single processor. 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 ///////////////////////////////////////////////////////////////////////////////////////// 6 ////////////////////////////////////////////////////////////////////////////////// 16 7 17 8 #include <giet_config.h> … … 24 15 #include <sys_handler.h> 25 16 26 /////////////////////////////////////////////////////////////////////////////////////////27 // A task context is an array of 64 words = 256 bytes.28 // It contains copies of processor registers (when the task is preempted):29 // - GPR[i], generally stored in slot (i). $0, $26 & $27 are not saved.30 // - HI & LO registers31 // - CP0 registers: EPC, SR, CR, BVAR32 // - CP2 registers : PTPR33 // It contains some general informations associated to the task:34 // - TTY : TTY channel global index35 // - NIC : NIC channel global index36 // - CMA : CMA channel global index37 // - HBA : HBA channel global index38 // - DMA : DMA channel local index39 // - TIM : TIM channel local index40 // - PTAB : page table virtual base address41 // - LTID : Task local index (in scheduler)42 // - VSID : Virtual space index43 // - RUN : Task state (0 => sleeping / 1 => runnable )44 // - TRDID : Thread ID index (in vspace)45 //46 // ctx[0]<- ***|ctx[8] <- $8 |ctx[16]<- $16|ctx[24]<- $24|ctx[32]<- EPC |ctx[40]<- TTY47 // ctx[1]<- $1 |ctx[9] <- $9 |ctx[17]<- $17|ctx[25]<- $25|ctx[33]<- CR |ctx[41]<- DMA48 // ctx[2]<- $2 |ctx[10]<- $10|ctx[18]<- $18|ctx[26]<- LO |ctx[34]<- SR |ctx[42]<- NIC49 // ctx[3]<- $3 |ctx[11]<- $11|ctx[19]<- $19|ctx[27]<- HI |ctx[35]<- BVAR |ctx[43]<- TIM50 // ctx[4]<- $4 |ctx[12]<- $12|ctx[20]<- $20|ctx[28]<- $28|ctx[36]<- PTAB |ctx[44]<- HBA51 // ctx[5]<- $5 |ctx[13]<- $13|ctx[21]<- $21|ctx[29]<- SP |ctx[37]<- LTID |ctx[45]<- CMA52 // ctx[6]<- $6 |ctx[14]<- $14|ctx[22]<- $22|ctx[30]<- $30|ctx[38]<- VSID |ctx[46]<- GTID53 // ctx[7]<- $7 |ctx[15]<- $15|ctx[23]<- $23|ctx[31]<- RA |ctx[39]<- PTPR |ctx[47]<- RUN54 //55 // ctx[48]<- TRDID56 //////////////////////////////////////////////////////////////////////////////////////////57 58 17 extern void _task_switch(unsigned int *, unsigned int *); 59 18 60 19 ///////////////////////////////////////////////////////////////////////////////// 61 // _ctx_switch()62 20 // This function performs a context switch between the running task 63 21 // and another task, using a round-robin sheduling policy between all … … 66 24 // If the only runable task is the current task, return without context switch. 67 25 // If there is no runable task, the scheduler switch to the default "idle" task. 68 // 26 ///////////////////////////////////////////////////////////////////////////////// 69 27 // Implementation note 70 28 // The return address contained in $31 is saved in the current task context … … 74 32 void _ctx_switch() 75 33 { 34 unsigned int gpid = _get_procid(); 35 unsigned int cluster_xy = gpid / NB_PROCS_MAX; 36 unsigned int lpid = gpid % NB_PROCS_MAX; 37 76 38 // get scheduler address 77 39 static_scheduler_t* psched = (static_scheduler_t*)_get_sched(); … … 105 67 } 106 68 107 // no switch if no change108 if (curr_task_id != next_task_id)109 {110 69 #if GIET_DEBUG_SWITCH 111 _tty_get_lock( 0 ); 112 _puts("\n[GIET DEBUG] Context switch for processor "); 113 _putd(_get_procid()); 114 _puts(" at cycle "); 115 _putd(_get_proctime()); 116 _puts("\n"); 117 _puts(" - tasks = "); 118 _putd(tasks); 119 _puts("\n"); 120 _puts(" - curr_task_id = "); 121 _putd( curr_task_id ); 122 _puts("\n"); 123 _puts(" - next_task_id = "); 124 _putd(next_task_id); 125 _puts("\n"); 126 _tty_release_lock( 0 ); 70 unsigned int x = cluster_xy >> Y_WIDTH; 71 unsigned int y = cluster_xy & ((1<<Y_WIDTH)-1); 72 73 _printf("\n[TASK SWITCH] (%d) -> (%d) on processor[%d,%d,%d] at cycle %d\n", 74 curr_task_id, next_task_id, x, y , lpid, _get_proctime() ); 127 75 #endif 128 76 77 if (curr_task_id != next_task_id) // actual task switch required 78 { 129 79 unsigned int* curr_ctx_vaddr = &(psched->context[curr_task_id][0]); 130 80 unsigned int* next_ctx_vaddr = &(psched->context[next_task_id][0]); 131 unsigned int procid = _get_procid();132 unsigned int local_id = procid % NB_PROCS_MAX;133 unsigned int cluster_id = procid / NB_PROCS_MAX;134 81 135 // reset timer counter 82 // reset timer counter. In each cluster, 83 // the NB_PROCS_MAX timers are system timers (TICK) 84 136 85 #if USE_XICU 137 _xcu_timer_reset_cpt( cluster_id, NB_PROCS_MAX + local_id);86 _xcu_timer_reset_cpt( cluster_xy, lpid ); 138 87 #else 139 _timer_reset_cpt( cluster_id, NB_PROCS_MAX + local_id);88 _timer_reset_cpt( cluster_xy, lpid); 140 89 #endif 141 90 … … 153 102 void _idle_task() 154 103 { 155 unsigned int count = GIET_IDLE_TASK_PERIOD;156 104 while(1) 157 105 { 158 #if GIET_IDLE_TASK_VERBOSITY == 1 159 _tty_get_lock( 0 ); 160 _puts("\n[GIET WARNING] Processor "); 161 _putd(_get_procid()); 162 _puts(" idle at cycle "); 163 _putd(_get_proctime()); 164 _puts("\n"); 165 _tty_release_lock( 0 ); 166 #endif 106 unsigned int count = GIET_IDLE_TASK_PERIOD; 167 107 108 // decounting loop 168 109 asm volatile( 169 110 "move $3, %0 \n" … … 176 117 : "$3" ); 177 118 178 count = GIET_IDLE_TASK_PERIOD; 119 // warning message 120 unsigned int gpid = _get_procid(); 121 unsigned int cluster_xy = gpid / NB_PROCS_MAX; 122 unsigned int lpid = gpid % NB_PROCS_MAX; 123 unsigned int x = cluster_xy >> Y_WIDTH; 124 unsigned int y = cluster_xy & ((1<<Y_WIDTH)-1); 125 126 _printf("\n[GIET WARNING] Processor[%d,%d,%d] still idle at cycle %d\n", 127 x, y, lpid, _get_proctime() ); 128 179 129 } 180 130 } // end ctx_idle() … … 182 132 183 133 ///////////////////////////////////////////////////////////////////////////////// 184 // The address of this function is used to initialise the return address134 // The address of this function is used to initialise the return address 185 135 // in the "idle" task context. 186 136 ///////////////////////////////////////////////////////////////////////////////// -
soft/giet_vm/giet_kernel/ctx_handler.h
r267 r294 1 ///////////////////////////////////////////////////////////////////////////////////////// 2 // File : ctx_handler.h 3 // Date : 01/04/2012 4 // Authors : alain greiner & joel porquet 5 // Copyright (c) UPMC-LIP6 6 ///////////////////////////////////////////////////////////////////////////////////////// 7 // The ctx_handler.h and ctx_handler.c files are part of the GIET-VM nano-kernel. 8 // This code is used to support context switch when several tasks are executing 9 // in time multiplexing on a single processor. 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 [13] is reserved for the "idle" task that does nothing, and 14 // is launched by the scheduler when there is no other runable task. 15 ///////////////////////////////////////////////////////////////////////////////////////// 16 // A task context is an array of 64 words = 256 bytes. 17 // It contains copies of processor registers (when the task is preempted): 18 // - GPR[i], generally stored in slot (i). $0, $26 & $27 are not saved. 19 // - HI & LO registers 20 // - CP0 registers: EPC, SR, CR, BVAR 21 // - CP2 registers : PTPR 22 // It contains some general informations associated to the task: 23 // - TTY : TTY channel global index 24 // - NIC : NIC channel global index 25 // - CMA : CMA channel global index 26 // - HBA : HBA channel global index 27 // - DMA : DMA channel local index 28 // - TIM : TIM channel local index 29 // - PTAB : page table virtual base address 30 // - LTID : Task local index (in scheduler) 31 // - VSID : Virtual space index 32 // - RUN : Task state (0 => sleeping / 1 => runnable ) 33 // - TRDID : Thread ID index (in vspace) 34 // 35 // ctx[0] <- *** |ctx[8] <- $8 |ctx[16]<- $16 |ctx[24]<- $24 36 // ctx[1] <- $1 |ctx[9] <- $9 |ctx[17]<- $17 |ctx[25]<- $25 37 // ctx[2] <- $2 |ctx[10]<- $10 |ctx[18]<- $18 |ctx[26]<- LO 38 // ctx[3] <- $3 |ctx[11]<- $11 |ctx[19]<- $19 |ctx[27]<- HI 39 // ctx[4] <- $4 |ctx[12]<- $12 |ctx[20]<- $20 |ctx[28]<- $28 40 // ctx[5] <- $5 |ctx[13]<- $13 |ctx[21]<- $21 |ctx[29]<- SP 41 // ctx[6] <- $6 |ctx[14]<- $14 |ctx[22]<- $22 |ctx[30]<- $30 42 // ctx[7] <- $7 |ctx[15]<- $15 |ctx[23]<- $23 |ctx[31]<- RA 43 // 44 // ctx[32]<- EPC |ctx[40]<- TTY |ctx[48]<- TRDID | 45 // ctx[33]<- CR |ctx[41]<- DMA 46 // ctx[34]<- SR |ctx[42]<- NIC 47 // ctx[35]<- BVAR |ctx[43]<- TIM 48 // ctx[36]<- PTAB |ctx[44]<- HBA 49 // ctx[37]<- LTID |ctx[45]<- CMA 50 // ctx[38]<- VSID |ctx[46]<- GTID 51 // ctx[39]<- PTPR |ctx[47]<- RUN 52 ///////////////////////////////////////////////////////////////////////////////////////// 53 1 54 #ifndef _CTX_HANDLER_H 2 55 #define _CTX_HANDLER_H … … 10 63 typedef struct static_scheduler_s 11 64 { 12 unsigned int context[1 5][64]; // at most 15 task contexts65 unsigned int context[14][64]; // at most 14 task (including idle_task) 13 66 unsigned int tasks; // actual number of tasks 14 67 unsigned int current; // current task index 15 unsigned int interrupt_vector[32]; // interrupt vector 68 unsigned int hwi_vector[32]; // hardware interrupt vector 69 unsigned int pti_vector[32]; // timer interrupt vector 70 unsigned int wti_vector[32]; // software interrupt vector 16 71 } static_scheduler_t; 17 72 … … 21 76 ///////////////////////////////////////////////////////////////////////////////// 22 77 23 #define IDLE_TASK_INDEX 1 478 #define IDLE_TASK_INDEX 13 24 79 25 80 ///////////////////////////////////////////////////////////////////////////////// … … 27 82 ///////////////////////////////////////////////////////////////////////////////// 28 83 29 #define CTX_SP_ID 29 30 #define CTX_RA_ID 31 84 #define CTX_SP_ID 29 // Stack Pointer 85 #define CTX_RA_ID 31 // Return Address 31 86 32 87 #define CTX_EPC_ID 32 // Exception Program Counter (CP0) … … 34 89 #define CTX_SR_ID 34 // Status Register (CP0) 35 90 #define CTX_BVAR_ID 35 // Bad Virtual Address Register (CP0) 36 37 91 #define CTX_PTAB_ID 36 // Page Table Virtual address 38 92 #define CTX_LTID_ID 37 // Local Task Index (in scheduler) … … 40 94 #define CTX_PTPR_ID 39 // Page Table Pointer Register (PADDR>>13) 41 95 42 #define CTX_TTY_ID 40 // global TTY terminal96 #define CTX_TTY_ID 40 // global TTY channel 43 97 #define CTX_DMA_ID 41 // local DMA channel 44 98 #define CTX_NIC_ID 42 // global NIC channel … … 48 102 #define CTX_GTID_ID 46 // Global Task Index 49 103 #define CTX_RUN_ID 47 // Boolean: task runable 104 50 105 #define CTX_TRDID_ID 48 // Thread Index in vspace 51 106 -
soft/giet_vm/giet_kernel/exc_handler.c
r258 r294 68 68 }; 69 69 70 /////////////////////////////////////////////// 71 static void _display_cause( unsigned int type ) 72 { 73 unsigned int gpid = _get_procid(); 74 unsigned int cluster_xy = gpid / NB_PROCS_MAX; 75 unsigned int lpid = gpid % NB_PROCS_MAX; 76 unsigned int x = cluster_xy >> Y_WIDTH; 77 unsigned int y = cluster_xy & ((1<<Y_WIDTH)-1); 78 unsigned int task = _get_context_slot(CTX_LTID_ID); 70 79 71 static void _display_cause(unsigned int type) 72 { 73 _tty_get_lock( 0 ); 74 _puts("\n[GIET] Exception for task "); 75 _putd(_get_context_slot(CTX_LTID_ID)); 76 _puts(" on processor "); 77 _putd(_get_procid()); 78 _puts(" at cycle "); 79 _putd(_get_proctime()); 80 _puts("\n - type : "); 81 _puts((char *) exc_type[type]); 82 _puts("\n - EPC : "); 83 _putx(_get_epc()); 84 _puts("\n - BVAR : "); 85 _putx(_get_bvar()); 86 _puts("\n"); 87 _puts("...Task desactivated\n"); 88 _tty_release_lock( 0 ); 80 _printf("\n[GIET] Exception for task %d on processor[%d,%d,%d] at cycle %d\n" 81 " - type : %s\n" 82 " - EPC : %x\n" 83 " - BVAR : %x\n" 84 "...Task desactivated\n", 85 task, x, y, lpid, _get_proctime(), 86 exc_type[type], _get_epc(), _get_bvar() ); 89 87 90 88 // goes to sleeping state -
soft/giet_vm/giet_kernel/irq_handler.c
r281 r294 4 4 // Author : alain greiner 5 5 // Copyright (c) UPMC-LIP6 6 ///////////////////////////////////////////////////////////////////////////////////7 // The irq_handler.c and irq_handler.h files are part of the GIET-VM nano-kernel.8 // They contain the code of the _irq_demux() function that access the XICU or9 // ICU component (Interupt Controler Unit), and the various ISRs (Interrupt10 // Service Routine) associated to the peripherals.11 6 /////////////////////////////////////////////////////////////////////////////////// 12 7 … … 19 14 #include <xcu_driver.h> 20 15 #include <tty_driver.h> 21 #include <ioc_driver.h> 16 #include <nic_driver.h> 17 #include <cma_driver.h> 18 #include <bdv_driver.h> 22 19 #include <dma_driver.h> 23 20 #include <mapping_info.h> … … 40 37 // Any value larger than 31 means "no active interrupt", and no ISR is executed. 41 38 // 42 // There is one interrupt vector per processor (stored in the scheduler associated43 // to the processor. Each interrupt vector entry contains four bits fields:44 // - isr_id bits[7:0] : defines the type of ISR to be executed.45 // - type_id bits[15:8] : IRQ_TYPE_HWI / IRQ_TYPE_SWI / IRQ_TYPE_PTI39 // There is three interrupt vectors per processor (stored in the processor's 40 // scheduler) for the three HWI, PTI, and WTI interrupts types. 41 // Each interrupt vector entry contains three bits fields: 42 // - isr_id bits[15:0] : defines the type of ISR to be executed. 46 43 // - channel_id bits[30:16] : defines the channel for multi-channels peripherals. 47 44 // - valid bit 31 : valid interrupt vector entry 48 // If the peripheral is replicated in clusters (TIMER or DMA), the channel_id is45 // If the peripheral is replicated in clusters, the channel_id is 49 46 // a global index : channel_id = cluster_id * NB_CHANNELS_MAX + loc_id 50 47 /////////////////////////////////////////////////////////////////////////////////// 51 48 void _irq_demux() 52 49 { 53 unsigned int gpid = _get_procid(); 54 unsigned int cluster_id = gpid / NB_PROCS_MAX; 55 unsigned int local_id = gpid % NB_PROCS_MAX; 50 unsigned int gpid = _get_procid(); 51 unsigned int cluster_xy = gpid / NB_PROCS_MAX; 52 unsigned int x = cluster_xy >> Y_WIDTH; 53 unsigned int y = cluster_xy & ((1<<Y_WIDTH)-1); 54 unsigned int lpid = gpid % NB_PROCS_MAX; 56 55 unsigned int irq_id; 57 unsigned int ko; 56 unsigned int irq_type; 57 char* irq_type_str[] = { "HWI", "WTI", "PTI" }; 58 58 59 59 // get the highest priority active IRQ index 60 61 unsigned int icu_out_index = local_id * IRQ_PER_PROCESSOR; 60 unsigned int icu_out_index = lpid * IRQ_PER_PROCESSOR; 62 61 63 62 #if USE_XICU 64 ko = _xcu_get_index( cluster_id, icu_out_index, &irq_id);63 _xcu_get_index( cluster_xy, icu_out_index, &irq_id, &irq_type ); 65 64 #else 66 ko = _icu_get_index( cluster_id, icu_out_index, &irq_id ); 67 #endif 68 69 if ( ko ) 70 { 71 _tty_get_lock( 0 ); 72 _puts("\n[GIET ERROR] Wrong _icu_read in _irq_demux()\n"); 73 _tty_release_lock( 0 ); 74 } 75 76 // do nothing if no interrupt active, or 65 irq_type = IRQ_TYPE_HWI; 66 _icu_get_index( cluster_xy, icu_out_index, &irq_id ); 67 #endif 68 77 69 if (irq_id < 32) 78 70 { 79 static_scheduler_t* psched = (static_scheduler_t*)_get_sched(); 80 unsigned int entry = psched->interrupt_vector[irq_id]; 81 unsigned int isr_id = (entry ) & 0x000000FF; 82 unsigned int type_id = (entry>> 8) & 0x000000FF; 83 unsigned int channel_id = (entry>>16) & 0x00007FFF; 84 85 if(type_id == IRQ_TYPE_HWI) // HWI 71 static_scheduler_t* psched = (static_scheduler_t*)_get_sched(); 72 unsigned int entry; 73 unsigned int isr_type; 74 unsigned int channel; 75 76 if (irq_type == IRQ_TYPE_HWI) entry = psched->hwi_vector[irq_id]; 77 else if (irq_type == IRQ_TYPE_PTI) entry = psched->pti_vector[irq_id]; 78 else if (irq_type == IRQ_TYPE_WTI) entry = psched->wti_vector[irq_id]; 79 else 86 80 { 87 if ( isr_id == ISR_SWITCH) _isr_switch(channel_id); 88 else if ( isr_id == ISR_IOC ) _isr_ioc(); 89 else if ( isr_id == ISR_TTY ) _isr_tty(channel_id); 90 else if ( isr_id == ISR_TIMER ) _isr_timer(channel_id); 91 else if ( isr_id == ISR_WAKUP ) _isr_timer(channel_id); 92 else _isr_default( irq_id, isr_id, type_id ); 81 _printf("\n[GIET ERROR] illegal irq_type in irq_demux()\n"); 82 _exit(); 93 83 } 94 else if(type_id == IRQ_TYPE_PTI) // PTI 84 85 isr_type = (entry ) & 0x0000FFFF; 86 channel = (entry>>16) & 0x00007FFF; 87 88 #if GIET_DEBUG_IRQS // we don't take the TTY lock to avoid deadlocks 89 _puts("\n[IRQS DEBUG] Processor["); 90 _putd(x); 91 _puts(","); 92 _putd(y); 93 _puts(","); 94 _putd(lpid); 95 _puts("] enters _irq_demux() at cycle "); 96 _putd(_get_proctime() ); 97 _puts("\n "); 98 _puts(irq_type_str[irq_type] ); 99 _puts(" : irq_id = "); 100 _putd(irq_id); 101 _puts(" / isr_type = "); 102 _putd(isr_type); 103 _puts(" / channel = "); 104 _putd(channel); 105 _puts("\n"); 106 #endif 107 108 // ISR call 109 if ( isr_type == ISR_TICK ) _isr_tick ( irq_type, irq_id, channel ); 110 else if ( isr_type == ISR_WAKUP ) _isr_wakup ( irq_type, irq_id, channel ); 111 else if ( isr_type == ISR_BDV ) _bdv_isr ( irq_type, irq_id, channel ); 112 else if ( isr_type == ISR_CMA ) _cma_isr ( irq_type, irq_id, channel ); 113 else if ( isr_type == ISR_TTY_RX ) _tty_rx_isr ( irq_type, irq_id, channel ); 114 else if ( isr_type == ISR_TTY_TX ) _tty_tx_isr ( irq_type, irq_id, channel ); 115 else if ( isr_type == ISR_NIC_RX ) _nic_rx_isr ( irq_type, irq_id, channel ); 116 else if ( isr_type == ISR_NIC_TX ) _nic_tx_isr ( irq_type, irq_id, channel ); 117 else if ( isr_type == ISR_TIMER ) _timer_isr ( irq_type, irq_id, channel ); 118 else 95 119 { 96 if ( isr_id == ISR_SWITCH) _isr_switch(irq_id); 97 else if ( isr_id == ISR_TIMER ) _isr_timer(irq_id); 98 else _isr_default( irq_id, isr_id, type_id ); 99 } 100 else if(type_id == IRQ_TYPE_SWI) // SWI 101 { 102 if ( isr_id == ISR_WAKUP ) return; 103 else _isr_default( irq_id, isr_id, type_id ); 120 // we don't take the TTY lock to avoid deadlock 121 _puts("\n[GIET ERROR] in _irq_demux() illegal ISR type on processor["); 122 _putd(x); 123 _puts(","); 124 _putd(y); 125 _puts(","); 126 _putd(lpid); 127 _puts("] at cycle "); 128 _putd(_get_proctime() ); 129 _puts("\n "); 130 _puts(irq_type_str[irq_type] ); 131 _puts(" : irq_id = "); 132 _putd(irq_id); 133 _puts(" / isr_type = "); 134 _putd(isr_type); 135 _puts(" / channel = "); 136 _putd(channel); 137 _puts("\n"); 138 _exit(); 104 139 } 105 140 } 106 } 107 108 /////////////////////////////////////////////////////////////////////////////////// 109 // The default ISR is called when no specific ISR has been installed in the 110 // interrupt vector. It simply displays an error message on kernel TTY[0]. 111 /////////////////////////////////////////////////////////////////////////////////// 112 void _isr_default( unsigned int irq_id, 113 unsigned int isr_id, 114 unsigned int type_id ) 115 { 116 _tty_get_lock( 0 ); 117 _puts("\n[GIET ERROR] Undefined ISR index = "); 118 _putd( isr_id ); 119 if(type_id == IRQ_TYPE_HWI) _puts(" / type = HWI "); 120 if(type_id == IRQ_TYPE_SWI) _puts(" / type = SWI "); 121 if(type_id == IRQ_TYPE_PTI) _puts(" / type = PTI "); 122 _puts(" / IRQ index = "); 123 _putd( irq_id ); 124 _puts(" / processor = "); 125 _putd( _get_procid() ); 126 _puts("\n"); 127 _tty_release_lock( 0 ); 128 _exit(); 129 } 130 131 132 /////////////////////////////////////////////////////////////////////////////////// 133 // This ISR is executed when a processor wakes up after a SWI interrup. 134 /////////////////////////////////////////////////////////////////////////////////// 135 void _isr_wakup() 136 { 137 _tty_get_lock( 0 ); 138 _puts("\n Processor "); 139 _putd( _get_procid() ); 140 _puts(" wake up\n"); 141 _tty_release_lock( 0 ); 142 } 143 144 /////////////////////////////////////////////////////////////////////////////////// 145 // There is only one IOC controler shared by all tasks. 146 // This ISR save the status, acknowledge the IRQ. 147 // and activates the task waiting on IO transfer. 148 // 149 // TODO the _set_task_slot access should be replaced by an atomic LL/SC 150 // when the CTX_RUN bool will be replaced by a bit_vector. 151 /////////////////////////////////////////////////////////////////////////////////// 152 void _isr_ioc() 153 { 154 // save status in _ioc_status variable and reset IRQ 155 if ( _ioc_get_status(0, &_ioc_status) ) return; 156 157 // reactivate task waiting on IOC 158 unsigned int gpid = _ioc_gtid>>16; 159 unsigned int ltid = _ioc_gtid & 0xFFFF; 160 161 _set_task_slot( gpid, // global processor index 162 ltid, // local task index (on processor) 163 CTX_RUN_ID, // CTX_RUN slot 164 1 ); // running 165 } 166 167 /////////////////////////////////////////////////////////////////////////////////// 168 // This ISR handles the IRQs generated by the "user" timers (the IRQs generated 169 // by the "system" timers should be handled by the _isr_switch(). 170 // These timers are distributed in all clusters, and can be implemented 171 // in a vci_multi_timer component, or in a vci_xicu component. 172 // The timer_id argument is the user timer local index. 173 // timer_globa_id = cluster_id*(NB_TIM_CHANNELS) + timer_id 174 // The ISR acknowledges the IRQ and registers the event in the proper entry 175 // of the _timer_event[] array, and a log message is displayed on kernel terminal. 176 /////////////////////////////////////////////////////////////////////////////////// 177 void _isr_timer(unsigned int timer_id) 178 { 179 // compute cluster_id 180 unsigned int cluster_id = _get_procid() / NB_PROCS_MAX; 181 182 // aknowledge IRQ 183 if (_timer_reset_irq( cluster_id, timer_id)) 141 else // no interrupt active 184 142 { 185 _tty_get_lock( 0 ); 186 _puts("[GIET ERROR] illegal timer index detected by _isr_timer\n"); 187 _tty_release_lock( 0 ); 188 return; 143 _isr_default(); 144 } 145 } 146 147 /////////////////////////////////////////////////////////////////////////////////// 148 // The default ISR is called when there is no active IRQ when the interrupt 149 // handler is called. It simply displays a warning message on TTY[0]. 150 /////////////////////////////////////////////////////////////////////////////////// 151 void _isr_default() 152 { 153 unsigned int gpid = _get_procid(); 154 unsigned int cluster_xy = gpid / NB_PROCS_MAX; 155 unsigned int x = cluster_xy >> Y_WIDTH; 156 unsigned int y = cluster_xy & ((1<<Y_WIDTH)-1); 157 unsigned int lpid = gpid % NB_PROCS_MAX; 158 159 // We don't take TTY lock to avoid deadlock 160 _puts("\n[GIET WARNING] IRQ handler called but no active IRQ on processor["); 161 _putd( x ); 162 _puts(","); 163 _putd( y ); 164 _puts(","); 165 _putd( lpid ); 166 _puts("] at cycle "); 167 _putd( _get_proctime() ); 168 _puts("\n "); 169 } 170 171 172 /////////////////////////////////////////////////////////////////////////////////// 173 // This ISR can only be executed after a WTI (IPI) to force a context switch 174 // on a remote processor. The context switch is only executed if the current task 175 // is the IDLE_TASK, or if the value written in the mailbox is non zero. 176 /////////////////////////////////////////////////////////////////////////////////// 177 void _isr_wakup( unsigned int irq_type, // HWI / WTI / PTI 178 unsigned int irq_id, // index returned by ICU 179 unsigned int channel ) // unused 180 { 181 unsigned int procid = _get_procid(); 182 unsigned int cluster_xy = procid / NB_PROCS_MAX; 183 unsigned int x = cluster_xy >> Y_WIDTH; 184 unsigned int y = cluster_xy & ((1<<Y_WIDTH)-1); 185 unsigned int lpid = procid % NB_PROCS_MAX; 186 unsigned int task = _get_current_task_id(); 187 unsigned int value; 188 189 if ( irq_type != IRQ_TYPE_WTI ) 190 { 191 // we don't take the TTY lock to avoid deadlocks 192 _puts("[GIET ERROR] _isr_wakup() not called by a WTI on processor["); 193 _putd( x ); 194 _puts(","); 195 _putd( y ); 196 _puts(","); 197 _putd( lpid ); 198 _puts("] at cycle "); 199 _putd( _get_proctime() ); 200 _puts("\n"); 201 _exit(); 189 202 } 190 203 191 #if NB_TIM_CHANNELS 192 // register the event 193 unsigned int timer_global_id = cluster_id * NB_TIM_CHANNELS + timer_id; 194 _user_timer_event[timer_global_id] = 1; 195 #endif 196 197 // display a message on TTY 0 198 _tty_get_lock( 0 ); 199 _puts("\n[GIET] User Timer IRQ at cycle "); 200 _putd(_get_proctime()); 201 _puts("\n - cluster_id = "); 202 _putd(cluster_id); 203 _puts("\n - timer_id = "); 204 _putd(timer_id); 205 _puts("\n"); 206 _tty_release_lock( 0 ); 207 } 208 209 210 /////////////////////////////////////////////////////////////////////////////////// 211 // This ISR handles the IRQs generated by the multi_tty controler, 212 // signaling that a character is available. 213 // There is one single multi_tty component controling all TTYs, 214 // and the tty_id argument is the global TTY index. 215 // There is one communication buffer _tty_buf[tty_id] per terminal. 216 // The sychronisation variable _tty_full[tty_id], is set by the ISR, 217 // and reset by the OS. 218 // A character is lost if the buffer is full when the ISR is executed. 219 /////////////////////////////////////////////////////////////////////////////////// 220 void _isr_tty(unsigned int tty_id) 221 { 222 // read character and reset IRQ in one read access 223 _tty_get_buf[tty_id] = _tty_read_data( tty_id ); 224 225 // signals character available 226 _tty_get_full[tty_id] = 1; 227 } 228 204 // get mailbox value and acknowledge WTI 205 _xcu_get_wti_value( cluster_xy, irq_id, &value ); 206 207 #if GIET_DEBUG_IRQS // we don't take the TTY lock to avoid deadlocks 208 _puts("\n[IRQS DEBUG] Processor["); 209 _putd( x ); 210 _puts(","); 211 _putd( y ); 212 _puts(","); 213 _putd( lpid ); 214 _puts("] enters _isr_wakup() at cycle "); 215 _putd( _get_proctime() ); 216 _puts("\n WTI / mailbox data = "); 217 _putx( value ); 218 _puts(" / current task index = "); 219 _putd( task ); 220 _puts("\n "); 221 #endif 222 223 // context swich if required 224 if ( (task == IDLE_TASK_INDEX) || (value != 0) ) _ctx_switch(); 225 } 229 226 230 227 ///////////////////////////////////////////////////////////////////////////////////// 231 // This ISR is in charge of context switch, and handle the IRQs generated by 232 // the "system" timers. 233 // The IRQs can be generated by the MULTI_TIMER component or by the XICU component, 234 // that are distributed in all clusters. 235 // The ISR acknowledges the IRQ and calls the _ctx_switch() function. 228 // This ISR is in charge of context switch, and handles the IRQs generated by 229 // the "system" timers contained in the MULTI_TIMER or in the XICU component. 230 // The ISR acknowledges the IRQ, and calls the _ctx_switch() function. 236 231 ///////////////////////////////////////////////////////////////////////////////////// 237 void _isr_switch( unsigned int timer_id) 238 { 239 // get cluster index 240 unsigned int cluster_id = _get_procid() / NB_PROCS_MAX; 241 242 // acknowledge IRQ 243 244 #if USE_XICU 245 if ( _xcu_timer_reset_irq( cluster_id, timer_id) ) 246 { 247 _tty_get_lock( 0 ); 248 _puts("[GIET ERROR] illegal proc index detected by _isr_switch\n"); 249 _tty_release_lock( 0 ); 250 return; 251 } 252 #else 253 if (_timer_reset_irq(cluster_id, timer_id)) 254 { 255 _tty_get_lock( 0 ); 256 _puts("[GIET ERROR] illegal proc index detected by _isr_switch\n"); 257 _tty_release_lock( 0 ); 258 return; 259 } 260 #endif 261 262 // performs the context switch 232 void _isr_tick( unsigned int irq_type, // HWI / WTI / PTI 233 unsigned int irq_id, // index returned by ICU 234 unsigned int channel ) // channel index if HWI 235 { 236 unsigned int procid = _get_procid(); 237 unsigned int cluster_xy = procid / NB_PROCS_MAX; 238 239 // acknowledge HWI or PTI 240 if ( irq_type == IRQ_TYPE_HWI ) _timer_reset_irq( cluster_xy, channel ); 241 else _xcu_timer_reset_irq( cluster_xy, irq_id ); 242 243 #if GIET_DEBUG_IRQS // we don't take the lock to avoid deadlock 244 unsigned int x = cluster_xy >> Y_WIDTH; 245 unsigned int y = cluster_xy & ((1<<Y_WIDTH)-1); 246 unsigned int lpid = procid % NB_PROCS_MAX; 247 _puts("\n[IRQS DEBUG] Processor["); 248 _putd( x ); 249 _puts(","); 250 _putd( y ); 251 _puts(","); 252 _putd( lpid ); 253 _puts("] enters _isr_tick() at cycle "); 254 _putd( _get_proctime() ); 255 _puts("\n "); 256 #endif 257 258 // context switch 263 259 _ctx_switch(); 264 260 } -
soft/giet_vm/giet_kernel/irq_handler.h
r258 r294 1 /////////////////////////////////////////////////////////////////////////////////// 2 // File : irq_handler.h 3 // Date : 01/04/2012 4 // Author : alain greiner 5 // Copyright (c) UPMC-LIP6 6 /////////////////////////////////////////////////////////////////////////////////// 7 // The irq_handler.c and irq_handler.h files are part of the GIET-VM nano-kernel. 8 // They contain the code of the _irq_demux() function that access the XICU or 9 // ICU component (Interupt Controler Unit), and the various ISRs (Interrupt 10 // Service Routine) associated to the various ISR types. 11 /////////////////////////////////////////////////////////////////////////////////// 12 1 13 #ifndef _IRQ_HANDLER_H 2 14 #define _IRQ_HANDLER_H 15 16 //////////////////////////////////////////////////////////////////////////////// 17 // This enum must be kept consistent with the values defined in the 18 // xml_driver.c and irq_handler.c files (for display) 19 /////////////////////////////////////////////////////////////////////////////// 3 20 4 21 enum isr_type_t 5 22 { 6 23 ISR_DEFAULT = 0, 7 ISR_ SWITCH= 1,8 ISR_TTY 9 ISR_ DMA= 3,10 ISR_ IOC= 4,24 ISR_TICK = 1, 25 ISR_TTY_RX = 2, 26 ISR_TTY_TX = 3, 27 ISR_BDV = 4, 11 28 ISR_TIMER = 5, 12 29 ISR_WAKUP = 6, 30 ISR_NIC_RX = 7, 31 ISR_NIC_TX = 8, 32 ISR_CMA = 9, 13 33 }; 14 15 34 16 35 /////////////////////////////////////////////////////////////////////////////// … … 21 40 22 41 extern void _isr_default(); 23 extern void _isr_ioc(); 24 extern void _isr_timer(unsigned int channel); 25 extern void _isr_dma(unsigned int channel); 26 extern void _isr_tty(unsigned int channel); 27 extern void _isr_switch(); 28 extern void _isr_wakup(); 42 43 extern void _isr_tick( unsigned int irq_type, 44 unsigned int irq_id, 45 unsigned int channel ); 46 47 extern void _isr_wakup( unsigned int irq_type, 48 unsigned int irq_id, 49 unsigned int channel ); 29 50 30 51 #endif -
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() -
soft/giet_vm/giet_kernel/sys_handler.c
r267 r294 35 35 &_timer_start, /* 0x04 */ 36 36 &_timer_stop, /* 0x05 */ 37 &_ sys_ukn,/* 0x06 */38 &_ sys_ukn,/* 0x07 */37 &_tty_get_lock, /* 0x06 */ 38 &_tty_release_lock, /* 0x07 */ 39 39 &_heap_info, /* 0x08 */ 40 40 &_local_task_id, /* 0x09 */ … … 49 49 &_fb_sync_read, /* 0x11 */ 50 50 &_thread_id, /* 0x12 */ 51 &_ tty_get_release_lock,/* 0x13 */51 &_sys_ukn, /* 0x13 */ 52 52 &_sys_ukn, /* 0x14 */ 53 53 &_sys_ukn, /* 0x15 */ … … 103 103 void _sys_ukn() 104 104 { 105 unsigned int epc; 106 asm volatile("mfc0 %0, $14" : "=r" (epc)); 107 108 _tty_get_lock( 0 ); 109 _puts("\n\n!!! Undefined System Call !!!\n"); 110 _puts("\nEPC = "); 111 _putx(epc); 112 _tty_release_lock( 0 ); 105 _printf("\n\n[GIET ERROR] Undefined System Call / EPC = %x\n", _get_epc() ); 113 106 _exit(); 114 107 } 115 108 116 109 //////////////////////////////////////////////////////////////////////////// 117 // _exit()118 110 // Task suicide... after printing a death message. 119 111 //////////////////////////////////////////////////////////////////////////// 120 void _task_exit() 121 { 122 unsigned int date = _get_proctime(); 123 unsigned int proc_id = _get_procid(); 124 unsigned int task_id = _get_context_slot(CTX_LTID_ID); 112 void _task_exit( char* string ) 113 { 114 unsigned int date = _get_proctime(); 115 unsigned int proc_id = _get_procid(); 116 unsigned int cluster_xy = proc_id / NB_PROCS_MAX; 117 unsigned int y = cluster_xy & ((1<<Y_WIDTH)-1); 118 unsigned int x = cluster_xy >> Y_WIDTH; 119 unsigned int lpid = proc_id % NB_PROCS_MAX; 120 unsigned int task_id = _get_context_slot(CTX_LTID_ID); 125 121 126 122 // print death message 127 _tty_get_lock( 0 ); 128 _puts("\n[GIET] Exit task "); 129 _putd(task_id); 130 _puts(" on processor "); 131 _putd(proc_id); 132 _puts(" at cycle "); 133 _putd(date); 134 _puts("\n\n"); 135 _tty_release_lock( 0 ); 123 _printf("\n[GIET] Exit task %d on processor[%d,%d,%d] at cycle %d" 124 "\n Cause : %s\n\n", 125 task_id, x, y, lpid, date, string ); 136 126 137 127 // goes to sleeping state … … 143 133 144 134 ////////////////////////////////////////////////////////////////////////////// 145 // _procnumber()146 135 // returns in buffer argument the number of processors in the cluster 147 136 // specified by the cluster_id argument. … … 165 154 166 155 ///////////////////////////////////////////////////////////////////////////// 167 // _local_task_id()168 156 // Returns current task local index. 169 157 ///////////////////////////////////////////////////////////////////////////// … … 174 162 175 163 ///////////////////////////////////////////////////////////////////////////// 176 // _global_task_id()177 164 // Returns current task global index. 178 165 ///////////////////////////////////////////////////////////////////////////// … … 183 170 184 171 ///////////////////////////////////////////////////////////////////////////// 185 // _thread_id()186 172 // Returns current thread index. 187 173 ///////////////////////////////////////////////////////////////////////////// … … 192 178 193 179 ///////////////////////////////////////////////////////////////////////////// 194 // _tty_get_release_lock(int val)195 // Get or release the hardware TTY lock depending on val (0: get,1: release)196 /////////////////////////////////////////////////////////////////////////////197 int _tty_get_release_lock(unsigned int val)198 {199 unsigned int channel = _get_context_slot(CTX_TTY_ID);200 201 if ( val == 0 ) _tty_get_lock(channel);202 else if ( val == 1 ) _tty_release_lock(channel);203 else return -1; // Wrong action204 205 return 0;206 }207 208 /////////////////////////////////////////////////////////////////////////////209 // _get_vobj()210 180 // This function writes in res_vobj a pointer on a vobj 211 181 // identified by the (vspace_name / vobj_name ) couple. 212 // The vobj_type argument is here only for the purpose of checking . 213 // returns 0: success, else: failed. 182 // returns 0 if success, >0 if not found 214 183 ///////////////////////////////////////////////////////////////////////////// 215 184 int _get_vobj( char* vspace_name, 216 185 char* vobj_name, 217 unsigned int vobj_type,218 186 mapping_vobj_t** res_vobj ) 219 187 { … … 237 205 if (_strncmp(vobj[vobj_id].name, vobj_name, 31) == 0) 238 206 { 239 if (vobj[vobj_id].type != vobj_type)240 {241 _tty_get_lock( 0 );242 _puts("*** Error in _get_obj: wrong type\n");243 _tty_release_lock( 0 );244 return -1; // wrong type245 }246 207 *res_vobj = &vobj[vobj_id]; 247 208 return 0; … … 250 211 } 251 212 } 252 _tty_get_lock( 0 ); 253 _puts("*** Error in _get_obj: object not found\n"); 254 _tty_release_lock( 0 ); 255 256 return -2; //not found 257 } 258 259 ///////////////////////////////////////////////////////////////////////////// 260 // _vobj_get_vbase() 213 return 1; //not found 214 } 215 216 ///////////////////////////////////////////////////////////////////////////// 261 217 // This function writes in vobj_vaddr the virtual base address of a vobj 262 218 // identified by the (vspace_name / vobj_name ) couple. 263 // The vobj_type argument is here only for the purpose of checking . 264 // returns 0: success, else: failed. 219 // returns 0 if success, >0 if not found 265 220 ///////////////////////////////////////////////////////////////////////////// 266 221 unsigned int _vobj_get_vbase( char* vspace_name, 267 222 char* vobj_name, 268 unsigned int vobj_type, 269 unsigned int* vobj_vaddr ) 223 unsigned int* vobj_vbase ) 270 224 { 271 225 mapping_vobj_t* res_vobj; 272 226 unsigned int ret; 273 if ((ret = _get_vobj(vspace_name, vobj_name, vobj_type,&res_vobj)))227 if ((ret = _get_vobj(vspace_name, vobj_name, &res_vobj))) 274 228 { 275 229 return ret; 276 230 } 277 *vobj_v addr= res_vobj->vaddr;231 *vobj_vbase = res_vobj->vaddr; 278 232 return 0; 279 233 } 280 234 281 235 ///////////////////////////////////////////////////////////////////////////// 282 // _vobj_get_length() 283 // This function writes in vobj_length the virtual base address of a vobj 236 // This function writes in vobj_length the length of a vobj 284 237 // identified by the (vspace_name / vobj_name ) couple. 285 // The vobj_type argument is here only for the purpose of checking . 286 // returns 0: success, else: failed. 238 // returns 0 if success, >0 if not found 287 239 ///////////////////////////////////////////////////////////////////////////// 288 240 unsigned int _vobj_get_length( char* vspace_name, 289 241 char* vobj_name, 290 unsigned int vobj_type,291 242 unsigned int* vobj_length ) 292 243 { 293 244 mapping_vobj_t * res_vobj; 294 245 unsigned int ret; 295 if ((ret = _get_vobj(vspace_name, vobj_name, vobj_type,&res_vobj)))246 if ((ret = _get_vobj(vspace_name, vobj_name, &res_vobj))) 296 247 { 297 248 return ret; … … 301 252 } 302 253 303 304 //////////////////////////////////////////////////////////////// 305 // _context_switch() 306 // This functions masks interruptions before calling _ctx_switch 307 // (They are usually masked when we receive a isr_switch interrupt 308 // because we execute ISRs with interrupt masked) 309 //////////////////////////////////////////////////////////////// 254 //////////////////////////////////////////////////////////////////////////// 255 // This sysrem function deschedule the requestint task. 256 // It mask interrupts before calling the _ctx_switch, and restore it 257 // when the task is rescheduled. 258 //////////////////////////////////////////////////////////////////////////// 310 259 void _context_switch() 311 260 { 312 _it_disable(); 261 unsigned int save_sr; 262 263 _it_disable( &save_sr ); 313 264 _ctx_switch(); 314 } 315 265 _it_restore( &save_sr ); 266 } 316 267 317 268 // Local Variables: -
soft/giet_vm/giet_kernel/sys_handler.h
r267 r294 20 20 21 21 void _sys_ukn(); 22 22 23 void _task_exit(); 24 23 25 void _context_switch(); 26 24 27 unsigned int _local_task_id(); 28 25 29 unsigned int _global_task_id(); 30 26 31 unsigned int _thread_id(); 27 28 int _tty_get_release_lock(unsigned int val);29 32 30 33 unsigned int _procs_number( unsigned int cluster_id, … … 33 36 unsigned int _vobj_get_vbase( char* vspace_name, 34 37 char* vobj_name, 35 unsigned vobj_type, 36 unsigned int* vobj_buffer); 38 unsigned int* vobj_vbase ); 39 40 unsigned int _vobj_get_length( char* vspace_name, 41 char* vobj_name, 42 unsigned int* vobj_length ); 37 43 38 44 #endif
Note: See TracChangeset
for help on using the changeset viewer.