Changeset 380 for trunk/hal/tsar_mips32
- Timestamp:
- Aug 14, 2017, 6:31:25 PM (7 years ago)
- Location:
- trunk/hal/tsar_mips32
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/hal/tsar_mips32/core/hal_exception.c
r317 r380 27 27 #include <thread.h> 28 28 #include <printk.h> 29 #include <chdev.h> 29 30 #include <vmm.h> 30 31 #include <errno.h> … … 37 38 #include <mips32_uzone.h> 38 39 40 39 41 ////////////////////////////////////////////////////////////////////////////////////////// 40 42 // Extern global variables 41 43 ////////////////////////////////////////////////////////////////////////////////////////// 42 44 43 extern remote_spinlock_t exception_lock; // allocated in the do_exception.c file.45 extern chdev_directory_t chdev_dir; // allocated in the kernel_init.c file. 44 46 45 47 ////////////////////////////////////////////////////////////////////////////////////////// … … 59 61 xcode_values_t; 60 62 61 /////////////////////////////////////// 63 ////////////////////////////////////////////////////////////////////////////////////////// 64 // This static function is called when a FPU Coprocessor Unavailable exception has been 65 // detected for the calling thread. 66 // It enables the FPU, It saves the current FPU context in the current owner thread 67 // descriptor if required, and restore the FPU context from the calling thread descriptor. 68 ////////////////////////////////////////////////////////////////////////////////////////// 69 // @ this : pointer on faulty thread descriptor. 70 // @ return always EXCP_NON_FATAL 71 ////////////////////////////////////////////////////////////////////////////////////////// 72 static error_t hal_fpu_exception( thread_t * this ) 73 { 74 core_t * core = this->core; 75 76 // enable FPU 77 hal_fpu_enable(); 78 79 // save FPU context in current owner thread if required 80 if( core->fpu_owner != NULL ) 81 { 82 if( core->fpu_owner != this ) 83 { 84 hal_fpu_context_save ( core->fpu_owner->fpu_context ); 85 } 86 } 87 88 // attach the FPU to the requesting thread 89 hal_fpu_context_restore( this->fpu_context ); 90 core->fpu_owner = this; 91 92 return EXCP_NON_FATAL; 93 94 } // end hal_fpu_exception() 95 96 ////////////////////////////////////////////////////////////////////////////////////////// 97 // This static function is called when an MMU exception has been detected. 98 // It get the relevant exception arguments from the MMU. 99 // It signal a fatal error in case of illegal access. In case of page unmapped 100 // it checks that the faulty address belongs to a registered vseg. It update the local 101 // vseg list from the reference cluster if required, and signal a fatal user error 102 // in case of illegal virtual address. Finally, it updates the local page table from the 103 // reference cluster. 104 ////////////////////////////////////////////////////////////////////////////////////////// 105 // @ this : pointer on faulty thread descriptor. 106 // @ return EXCP_NON_FATAL / EXCP_USER_ERROR / EXCP_KERNEL_PANIC 107 ////////////////////////////////////////////////////////////////////////////////////////// 108 static error_t hal_mmu_exception( thread_t * this ) 109 { 110 vseg_t * vseg; // vseg containing the bad_vaddr 111 process_t * process; // local process descriptor 112 error_t error; // return value 113 114 reg_t mmu_ins_excp_code; 115 reg_t mmu_ins_bad_vaddr; 116 reg_t mmu_dat_excp_code; 117 reg_t mmu_dat_bad_vaddr; 118 119 intptr_t bad_vaddr; 120 uint32_t excp_code; 121 122 process = this->process; 123 124 // get relevant values from MMU 125 hal_get_mmu_excp( &mmu_ins_excp_code, 126 &mmu_ins_bad_vaddr, 127 &mmu_dat_excp_code, 128 &mmu_dat_bad_vaddr ); 129 130 // get exception code and faulty vaddr 131 if( mmu_ins_excp_code ) 132 { 133 excp_code = mmu_ins_excp_code; 134 bad_vaddr = mmu_ins_bad_vaddr; 135 } 136 else if( mmu_dat_excp_code ) 137 { 138 excp_code = mmu_dat_excp_code; 139 bad_vaddr = mmu_dat_bad_vaddr; 140 } 141 else 142 { 143 return EXCP_NON_FATAL; 144 } 145 146 vmm_dmsg("\n[INFO] %s : enters for thread %x / process %x" 147 " / bad_vaddr = %x / excep_code = %x\n", 148 __FUNCTION__, this->trdid , process->pid , bad_vaddr , excp_code ); 149 150 // a kernel thread should not rise an MMU exception 151 if( this->type != THREAD_USER ) 152 { 153 printk("\n[PANIC] in %s : thread %x is a kernel thread / vaddr = %x\n", 154 __FUNCTION__ , this->trdid , bad_vaddr ); 155 return EXCP_KERNEL_PANIC; 156 } 157 158 // enable IRQs 159 hal_enable_irq( NULL ); 160 161 // vaddr must be contained in a registered vseg 162 vseg = vmm_get_vseg( process , bad_vaddr ); 163 164 if( vseg == NULL ) // vseg not found in local cluster 165 { 166 // get extended pointer on reference process 167 xptr_t ref_xp = process->ref_xp; 168 169 // get cluster and local pointer on reference process 170 cxy_t ref_cxy = GET_CXY( ref_xp ); 171 process_t * ref_ptr = (process_t *)GET_PTR( ref_xp ); 172 173 if( local_cxy != ref_cxy ) // reference process is remote 174 { 175 // get extended pointer on reference vseg 176 xptr_t vseg_xp; 177 rpc_vmm_get_ref_vseg_client( ref_cxy , ref_ptr , bad_vaddr , &vseg_xp ); 178 179 180 if( vseg == NULL ) // vseg not found => illegal user vaddr 181 { 182 printk("\n[ERROR] in %s for thread %x : illegal vaddr = %x\n", 183 __FUNCTION__ , this->trdid , bad_vaddr ); 184 185 hal_disable_irq( NULL ); 186 return EXCP_USER_ERROR; 187 } 188 else // vseg found => make a local copy 189 { 190 // allocate a vseg in local cluster 191 vseg = vseg_alloc(); 192 193 if( vseg == NULL ) 194 { 195 printk("\n[PANIC] in %s : no memory for vseg / thread = %x\n", 196 __FUNCTION__ , this->trdid ); 197 hal_disable_irq( NULL ); 198 return EXCP_KERNEL_PANIC; 199 } 200 201 // initialise local vseg from reference 202 vseg_init_from_ref( vseg , ref_xp ); 203 204 // register local vseg in local VMM 205 error = vseg_attach( &process->vmm , vseg ); 206 } 207 } 208 else // reference is local => illegal user vaddr 209 { 210 printk("\n[ERROR] in %s for thread %x : illegal vaddr = %x\n", 211 __FUNCTION__ , this->trdid , bad_vaddr ); 212 213 hal_disable_irq( NULL ); 214 return EXCP_USER_ERROR; 215 } 216 } 217 218 vmm_dmsg("\n[INFO] %s : found vseg for thread %x / vseg_min = %x / vseg_max = %x\n", 219 __FUNCTION__ , this->trdid , vseg->min , vseg->max ); 220 221 // analyse exception code 222 if( excp_code & MMU_EXCP_PAGE_UNMAPPED ) 223 { 224 // try to map the unmapped PTE 225 error = vmm_handle_page_fault( process, 226 vseg, 227 bad_vaddr >> CONFIG_PPM_PAGE_SHIFT ); // vpn 228 229 if( error ) 230 { 231 printk("\n[PANIC] in %s for thread %x : cannot map legal vaddr = %x\n", 232 __FUNCTION__ , this->trdid , bad_vaddr ); 233 234 hal_disable_irq( NULL ); 235 return EXCP_KERNEL_PANIC; 236 } 237 else 238 { 239 vmm_dmsg("\n[INFO] %s : page fault handled for vaddr = %x in thread %x\n", 240 __FUNCTION__ , bad_vaddr , this->trdid ); 241 242 // page fault successfully handled 243 hal_disable_irq( NULL ); 244 return EXCP_NON_FATAL; 245 } 246 } 247 else if( excp_code & MMU_EXCP_USER_PRIVILEGE ) 248 { 249 printk("\n[ERROR] in %s for thread %x : user access to kernel vseg at vaddr = %x\n", 250 __FUNCTION__ , this->trdid , bad_vaddr ); 251 252 hal_disable_irq( NULL ); 253 return EXCP_USER_ERROR; 254 } 255 else if( excp_code & MMU_EXCP_USER_EXEC ) 256 { 257 printk("\n[ERROR] in %s for thread %x : access to non-exec vseg at vaddr = %x\n", 258 __FUNCTION__ , this->trdid , bad_vaddr ); 259 260 hal_disable_irq( NULL ); 261 return EXCP_USER_ERROR; 262 } 263 else if( excp_code & MMU_EXCP_USER_WRITE ) 264 { 265 printk("\n[ERROR] in %s for thread %x : write to non-writable vseg at vaddr = %x\n", 266 __FUNCTION__ , this->trdid , bad_vaddr ); 267 268 hal_disable_irq( NULL ); 269 return EXCP_USER_ERROR; 270 } 271 272 else // this is a kernel error => panic 273 { 274 printk("\n[PANIC] in %s for thread %x : kernel exception = %x / vaddr = %x\n", 275 __FUNCTION__ , this->trdid , excp_code , bad_vaddr ); 276 277 hal_disable_irq( NULL ); 278 return EXCP_KERNEL_PANIC; 279 } 280 281 } // end hal_mmu_exception() 282 283 ////////////////////////////////////////////////////////////////////////////////////////// 284 // This static function prints on the kernel terminal the saved context (core registers) 285 // and the thread state of a faulty thread. 286 ////////////////////////////////////////////////////////////////////////////////////////// 287 // @ this : pointer on faulty thread descriptor. 288 // @ regs_tbl : pointer on register array. 289 // @ return always EXCP_NON_FATAL 290 ////////////////////////////////////////////////////////////////////////////////////////// 291 static void hal_exception_dump( thread_t * this, 292 reg_t * regs_tbl ) 293 { 294 uint32_t save_sr; 295 296 // get pointers on TXT0 chdev 297 xptr_t txt0_xp = chdev_dir.txt[0]; 298 cxy_t txt0_cxy = GET_CXY( txt0_xp ); 299 chdev_t * txt0_ptr = GET_PTR( txt0_xp ); 300 301 // get extended pointer on remote TXT0 chdev lock 302 xptr_t lock_xp = XPTR( txt0_cxy , &txt0_ptr->wait_lock ); 303 304 // get TXT0 lock in busy waiting mode 305 remote_spinlock_lock_busy( lock_xp , &save_sr ); 306 307 if( this->type == THREAD_USER ) 308 nolock_printk("\n================= USER ERROR / cycle %d ====================\n", 309 hal_time_stamp() ); 310 else 311 nolock_printk("\n================= KERNEL PANIC / cycle %d ==================\n", 312 hal_time_stamp() ); 313 314 nolock_printk(" thread type = %s / trdid = %x / pid %x / core[%x,%d]\n" 315 " local locks = %d / remote locks = %d / blocked_vector = %X\n\n", 316 thread_type_str(this->type), this->trdid, this->process->pid, local_cxy, 317 this->core->lid, this->local_locks, this->remote_locks, this->blocked ); 318 319 nolock_printk("CR %X EPC %X SR %X SP %X\n", 320 regs_tbl[UZ_CR], regs_tbl[UZ_EPC], regs_tbl[UZ_SR], regs_tbl[UZ_SP]); 321 322 nolock_printk("at_1 %X v0_2 %X v1_3 %X a0_4 %X a1_5 %X\n", 323 regs_tbl[UZ_AT], regs_tbl[UZ_V0], regs_tbl[UZ_V1], regs_tbl[UZ_A0], regs_tbl[UZ_A1]); 324 325 nolock_printk("a2_6 %X a3_7 %X t0_8 %X t1_9 %X t2_10 %X\n", 326 regs_tbl[UZ_A2],regs_tbl[UZ_A3],regs_tbl[UZ_T0],regs_tbl[UZ_T1],regs_tbl[UZ_T2]); 327 328 nolock_printk("t3_11 %X t4_12 %X t5_13 %X t6_14 %X t7_15 %X\n", 329 regs_tbl[UZ_T3],regs_tbl[UZ_T4],regs_tbl[UZ_T5],regs_tbl[UZ_T6],regs_tbl[UZ_T7]); 330 331 nolock_printk("t8_24 %X t9_25 %X gp_28 %X c0_hi %X c0_lo %X\n", 332 regs_tbl[UZ_T8],regs_tbl[UZ_T9],regs_tbl[UZ_GP],regs_tbl[UZ_HI],regs_tbl[UZ_LO]); 333 334 nolock_printk("s0_16 %X s1_17 %X s2_18 %X s3_19 %X s4_20 %X\n", 335 regs_tbl[UZ_S0],regs_tbl[UZ_S1],regs_tbl[UZ_S2],regs_tbl[UZ_S3],regs_tbl[UZ_S4]); 336 337 nolock_printk("s5_21 %X s6_22 %X s7_23 %X s8_30 %X ra_31 %X\n", 338 regs_tbl[UZ_S5],regs_tbl[UZ_S6],regs_tbl[UZ_S7],regs_tbl[UZ_S8],regs_tbl[UZ_RA]); 339 340 // release the lock 341 remote_spinlock_unlock_busy( lock_xp , save_sr ); 342 343 } // end hal_exception_dump() 344 345 346 /////////////////////////////////////////////////////////////////////////////// 347 // TODO replace the hal_core_sleep() by the generic panic() function. 348 /////////////////////////////////////////////////////////////////////////////// 62 349 void hal_do_exception( thread_t * this, 63 350 reg_t * regs_tbl ) … … 72 359 { 73 360 case XCODE_DBE: // can be non fatal 74 case XCODE_IBE: // ca ll generic excepton handler for a MMU exception75 { 76 error = do_exception( this , true);361 case XCODE_IBE: // can be non fatal 362 { 363 error = hal_mmu_exception( this ); 77 364 } 78 365 break; 79 366 80 367 case XCODE_CPU: // can be non fatal 81 // call generic excepton handler for a FPU exception82 368 { 83 369 if( ((regs_tbl[UZ_CR] >> 28) & 0x3) == 1 ) // unavailable FPU 84 370 { 85 error = do_exception( this , false);371 error = hal_fpu_exception( this ); 86 372 } 87 373 else … … 92 378 break; 93 379 94 case XCODE_OVR: // user fatal error95 case XCODE_RI: // user fatal error96 case XCODE_ADEL: // user fatal error97 case XCODE_ADES: // kill process380 case XCODE_OVR: // user fatal error 381 case XCODE_RI: // user fatal error 382 case XCODE_ADEL: // user fatal error 383 case XCODE_ADES: // user fatal error 98 384 { 99 385 error = EXCP_USER_ERROR; … … 120 406 } // end hal_do_exception() 121 407 122 ///////////////////////////////////////// 123 void hal_exception_dump( thread_t * this, 124 reg_t * regs_tbl ) 125 { 126 // take the exception_lock located in io_cluster 127 remote_spinlock_lock( XPTR( LOCAL_CLUSTER->io_cxy , &exception_lock ) ); 128 129 if( this->type == THREAD_USER ) 130 printk("\n================= USER ERROR / cycle %d ====================\n", 131 hal_time_stamp() ); 132 else 133 printk("\n================= KERNEL PANIC / cycle %d ==================\n", 134 hal_time_stamp() ); 135 136 printk(" thread type = %s / trdid = %x / pid %x / core[%x,%d]\n" 137 " local locks = %d / remote locks = %d / blocked_vector = %X\n\n", 138 thread_type_str(this->type), this->trdid, this->process->pid, local_cxy, 139 this->core->lid, this->local_locks, this->remote_locks, this->blocked ); 140 141 printk("CR %X EPC %X SR %X SP %X\n", 142 regs_tbl[UZ_CR], regs_tbl[UZ_EPC], regs_tbl[UZ_SR], regs_tbl[UZ_SP]); 143 144 printk("at_1 %X v0_2 %X v1_3 %X a0_4 %X a1_5 %X\n", 145 regs_tbl[UZ_AT], regs_tbl[UZ_V0], regs_tbl[UZ_V1], regs_tbl[UZ_A0], regs_tbl[UZ_A1]); 146 147 printk("a2_6 %X a3_7 %X t0_8 %X t1_9 %X t2_10 %X\n", 148 regs_tbl[UZ_A2],regs_tbl[UZ_A3],regs_tbl[UZ_T0],regs_tbl[UZ_T1],regs_tbl[UZ_T2]); 149 150 printk("t3_11 %X t4_12 %X t5_13 %X t6_14 %X t7_15 %X\n", 151 regs_tbl[UZ_T3],regs_tbl[UZ_T4],regs_tbl[UZ_T5],regs_tbl[UZ_T6],regs_tbl[UZ_T7]); 152 153 printk("t8_24 %X t9_25 %X gp_28 %X c0_hi %X c0_lo %X\n", 154 regs_tbl[UZ_T8],regs_tbl[UZ_T9],regs_tbl[UZ_GP],regs_tbl[UZ_HI],regs_tbl[UZ_LO]); 155 156 printk("s0_16 %X s1_17 %X s2_18 %X s3_19 %X s4_20 %X\n", 157 regs_tbl[UZ_S0],regs_tbl[UZ_S1],regs_tbl[UZ_S2],regs_tbl[UZ_S3],regs_tbl[UZ_S4]); 158 159 printk("s5_21 %X s6_22 %X s7_23 %X s8_30 %X ra_31 %X\n", 160 regs_tbl[UZ_S5],regs_tbl[UZ_S6],regs_tbl[UZ_S7],regs_tbl[UZ_S8],regs_tbl[UZ_RA]); 161 162 // release the exception_lock 163 remote_spinlock_unlock( XPTR( LOCAL_CLUSTER->io_cxy , &exception_lock ) ); 164 165 } // end hal_exception_dump() 166 408 -
trunk/hal/tsar_mips32/drivers/soclib_pic.c
r337 r380 491 491 uint32_t * base = soclib_pic_xcu_base(); 492 492 493 // set period value in XCU 494 base[(XCU_PTI_PER << 5) | lid] = period; 493 // set period value in XCU (in cycles) 494 uint32_t cycles = period * SOCLIB_CYCLES_PER_MS * CONFIG_SCHED_TICK_MS_PERIOD; 495 base[(XCU_PTI_PER << 5) | lid] = cycles; 495 496 496 497 // enable PTI in local XCU controller -
trunk/hal/tsar_mips32/drivers/soclib_pic.h
r279 r380 90 90 #define SOCLIB_MAX_PTI 16 91 91 92 #define SOCLIB_CYCLES_PER_MS 1000 // for a SystemC virtual prototype 93 92 94 /****************************************************************************************** 93 95 * This define the registers offsets for the external SOCLIB_IOPIC component. … … 231 233 * The <period> argument define the number of cycles between IRQs. 232 234 ****************************************************************************************** 233 * @ period : number of cycles between IRQs.235 * @ period : number of ticks between IRQs. 234 236 *****************************************************************************************/ 235 237 void soclib_pic_enable_timer( uint32_t period );
Note: See TracChangeset
for help on using the changeset viewer.