Changes in kernel/arch/mips32/src/start.S [0c39b96:96e0748d] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
kernel/arch/mips32/src/start.S
r0c39b96 r96e0748d 45 45 .global userspace_asm 46 46 47 /* 48 * Which status bits are thread-local: 49 * KSU(UM), EXL, ERL, IE 50 */ 51 #define REG_SAVE_MASK 0x1f 52 53 #define ISTATE_OFFSET_A0 0 54 #define ISTATE_OFFSET_A1 4 55 #define ISTATE_OFFSET_A2 8 56 #define ISTATE_OFFSET_A3 12 57 #define ISTATE_OFFSET_T0 16 58 #define ISTATE_OFFSET_T1 20 59 #define ISTATE_OFFSET_V0 24 60 #define ISTATE_OFFSET_V1 28 61 #define ISTATE_OFFSET_AT 32 62 #define ISTATE_OFFSET_T2 36 63 #define ISTATE_OFFSET_T3 40 64 #define ISTATE_OFFSET_T4 44 65 #define ISTATE_OFFSET_T5 48 66 #define ISTATE_OFFSET_T6 52 67 #define ISTATE_OFFSET_T7 56 68 #define ISTATE_OFFSET_S0 60 69 #define ISTATE_OFFSET_S1 64 70 #define ISTATE_OFFSET_S2 68 71 #define ISTATE_OFFSET_S3 72 72 #define ISTATE_OFFSET_S4 76 73 #define ISTATE_OFFSET_S5 80 74 #define ISTATE_OFFSET_S6 84 75 #define ISTATE_OFFSET_S7 88 76 #define ISTATE_OFFSET_T8 92 77 #define ISTATE_OFFSET_T9 96 78 #define ISTATE_OFFSET_KT0 100 79 #define ISTATE_OFFSET_KT1 104 80 #define ISTATE_OFFSET_GP 108 81 #define ISTATE_OFFSET_SP 112 82 #define ISTATE_OFFSET_S8 116 83 #define ISTATE_OFFSET_RA 120 84 #define ISTATE_OFFSET_LO 124 85 #define ISTATE_OFFSET_HI 128 86 #define ISTATE_OFFSET_STATUS 132 87 #define ISTATE_OFFSET_EPC 136 88 #define ISTATE_OFFSET_ALIGNMENT 140 89 90 #define ISTATE_SOFT_SIZE 144 91 92 /* 93 * The fake ABI prologue is never executed and may not be part of the 94 * procedure's body. Instead, it should be immediately preceding the procedure's 95 * body. Its only purpose is to trick the stack trace walker into thinking that 96 * the exception is more or less just a normal function call. 97 */ 98 .macro FAKE_ABI_PROLOGUE 99 sub $sp, ISTATE_SOFT_SIZE 100 sw $ra, ISTATE_OFFSET_EPC($sp) 101 .endm 102 103 /* 104 * Save registers to space defined by \r 105 * We will change status: Disable ERL, EXL, UM, IE 106 * These changes will be automatically reversed in REGISTER_LOAD 107 * %sp is NOT saved as part of these registers 108 */ 47 # Which status bits should are thread-local 48 #define REG_SAVE_MASK 0x1f # KSU(UM), EXL, ERL, IE 49 50 # Save registers to space defined by \r 51 # We will change status: Disable ERL,EXL,UM,IE 52 # These changes will be automatically reversed in REGISTER_LOAD 53 # SP is NOT saved as part of these registers 109 54 .macro REGISTERS_STORE_AND_EXC_RESET r 110 sw $at, ISTATE_OFFSET_AT(\r) 111 sw $v0, ISTATE_OFFSET_V0(\r) 112 sw $v1, ISTATE_OFFSET_V1(\r) 113 sw $a0, ISTATE_OFFSET_A0(\r) 114 sw $a1, ISTATE_OFFSET_A1(\r) 115 sw $a2, ISTATE_OFFSET_A2(\r) 116 sw $a3, ISTATE_OFFSET_A3(\r) 117 sw $t0, ISTATE_OFFSET_T0(\r) 118 sw $t1, ISTATE_OFFSET_T1(\r) 119 sw $t2, ISTATE_OFFSET_T2(\r) 120 sw $t3, ISTATE_OFFSET_T3(\r) 121 sw $t4, ISTATE_OFFSET_T4(\r) 122 sw $t5, ISTATE_OFFSET_T5(\r) 123 sw $t6, ISTATE_OFFSET_T6(\r) 124 sw $t7, ISTATE_OFFSET_T7(\r) 125 sw $t8, ISTATE_OFFSET_T8(\r) 126 sw $t9, ISTATE_OFFSET_T9(\r) 127 sw $s0, ISTATE_OFFSET_S0(\r) 128 sw $s1, ISTATE_OFFSET_S1(\r) 129 sw $s2, ISTATE_OFFSET_S2(\r) 130 sw $s3, ISTATE_OFFSET_S3(\r) 131 sw $s4, ISTATE_OFFSET_S4(\r) 132 sw $s5, ISTATE_OFFSET_S5(\r) 133 sw $s6, ISTATE_OFFSET_S6(\r) 134 sw $s7, ISTATE_OFFSET_S7(\r) 135 sw $s8, ISTATE_OFFSET_S8(\r) 136 55 sw $at, EOFFSET_AT(\r) 56 sw $v0, EOFFSET_V0(\r) 57 sw $v1, EOFFSET_V1(\r) 58 sw $a0, EOFFSET_A0(\r) 59 sw $a1, EOFFSET_A1(\r) 60 sw $a2, EOFFSET_A2(\r) 61 sw $a3, EOFFSET_A3(\r) 62 sw $t0, EOFFSET_T0(\r) 63 sw $t1, EOFFSET_T1(\r) 64 sw $t2, EOFFSET_T2(\r) 65 sw $t3, EOFFSET_T3(\r) 66 sw $t4, EOFFSET_T4(\r) 67 sw $t5, EOFFSET_T5(\r) 68 sw $t6, EOFFSET_T6(\r) 69 sw $t7, EOFFSET_T7(\r) 70 sw $t8, EOFFSET_T8(\r) 71 sw $t9, EOFFSET_T9(\r) 72 137 73 mflo $at 138 sw $at, ISTATE_OFFSET_LO(\r)74 sw $at, EOFFSET_LO(\r) 139 75 mfhi $at 140 sw $at, ISTATE_OFFSET_HI(\r) 141 142 sw $gp, ISTATE_OFFSET_GP(\r) 143 sw $ra, ISTATE_OFFSET_RA(\r) 144 sw $k0, ISTATE_OFFSET_KT0(\r) 145 sw $k1, ISTATE_OFFSET_KT1(\r) 146 76 sw $at, EOFFSET_HI(\r) 77 78 sw $gp, EOFFSET_GP(\r) 79 sw $ra, EOFFSET_RA(\r) 80 sw $k1, EOFFSET_K1(\r) 81 147 82 mfc0 $t0, $status 148 83 mfc0 $t1, $epc 149 84 150 /* save only KSU, EXL, ERL, IE */ 151 and $t2, $t0, REG_SAVE_MASK 152 153 /* clear KSU, EXL, ERL, IE */ 154 li $t3, ~(REG_SAVE_MASK) 155 and $t0, $t0, $t3 156 157 sw $t2, ISTATE_OFFSET_STATUS(\r) 158 sw $t1, ISTATE_OFFSET_EPC(\r) 85 and $t2, $t0, REG_SAVE_MASK # Save only KSU,EXL,ERL,IE 86 li $t3, ~(0x1f) 87 and $t0, $t0, $t3 # Clear KSU,EXL,ERL,IE 88 89 sw $t2,EOFFSET_STATUS(\r) 90 sw $t1,EOFFSET_EPC(\r) 159 91 mtc0 $t0, $status 160 92 .endm 161 93 162 94 .macro REGISTERS_LOAD r 163 /* 164 * Update only UM, EXR, IE from status, the rest 165 * is controlled by OS and not bound to task. 166 */ 95 # Update only UM,EXR,IE from status, the rest 96 # is controlled by OS and not bound to task 167 97 mfc0 $t0, $status 168 lw $t1, ISTATE_OFFSET_STATUS(\r) 169 170 /* mask UM, EXL, ERL, IE */ 171 li $t2, ~REG_SAVE_MASK 98 lw $t1,EOFFSET_STATUS(\r) 99 100 li $t2, ~REG_SAVE_MASK # Mask UM,EXL,ERL,IE 172 101 and $t0, $t0, $t2 173 102 174 /* copy UM, EXL, ERL, IE from saved status */ 175 or $t0, $t0, $t1 103 or $t0, $t0, $t1 # Copy UM,EXL, ERL, IE from saved status 176 104 mtc0 $t0, $status 177 105 178 lw $v0, ISTATE_OFFSET_V0(\r)179 lw $v1, ISTATE_OFFSET_V1(\r)180 lw $a0, ISTATE_OFFSET_A0(\r)181 lw $a1, ISTATE_OFFSET_A1(\r)182 lw $a2, ISTATE_OFFSET_A2(\r)183 lw $a3, ISTATE_OFFSET_A3(\r)184 lw $t0, ISTATE_OFFSET_T0(\r)185 lw $t1, ISTATE_OFFSET_T1(\r)186 lw $t2, ISTATE_OFFSET_T2(\r)187 lw $t3, ISTATE_OFFSET_T3(\r)188 lw $t4, ISTATE_OFFSET_T4(\r)189 lw $t5, ISTATE_OFFSET_T5(\r)190 lw $t6, ISTATE_OFFSET_T6(\r)191 lw $t7, ISTATE_OFFSET_T7(\r)192 lw $t8, ISTATE_OFFSET_T8(\r)193 lw $t9, ISTATE_OFFSET_T9(\r)194 195 lw $gp, ISTATE_OFFSET_GP(\r)196 lw $ra, ISTATE_OFFSET_RA(\r)197 lw $k1, ISTATE_OFFSET_KT1(\r)198 199 lw $at, ISTATE_OFFSET_LO(\r)106 lw $v0, EOFFSET_V0(\r) 107 lw $v1, EOFFSET_V1(\r) 108 lw $a0, EOFFSET_A0(\r) 109 lw $a1, EOFFSET_A1(\r) 110 lw $a2, EOFFSET_A2(\r) 111 lw $a3, EOFFSET_A3(\r) 112 lw $t0, EOFFSET_T0(\r) 113 lw $t1, EOFFSET_T1(\r) 114 lw $t2, EOFFSET_T2(\r) 115 lw $t3, EOFFSET_T3(\r) 116 lw $t4, EOFFSET_T4(\r) 117 lw $t5, EOFFSET_T5(\r) 118 lw $t6, EOFFSET_T6(\r) 119 lw $t7, EOFFSET_T7(\r) 120 lw $t8, EOFFSET_T8(\r) 121 lw $t9, EOFFSET_T9(\r) 122 123 lw $gp, EOFFSET_GP(\r) 124 lw $ra, EOFFSET_RA(\r) 125 lw $k1, EOFFSET_K1(\r) 126 127 lw $at, EOFFSET_LO(\r) 200 128 mtlo $at 201 lw $at, ISTATE_OFFSET_HI(\r)129 lw $at, EOFFSET_HI(\r) 202 130 mthi $at 203 204 lw $at, ISTATE_OFFSET_EPC(\r)131 132 lw $at, EOFFSET_EPC(\r) 205 133 mtc0 $at, $epc 206 134 207 lw $at, ISTATE_OFFSET_AT(\r)208 lw $sp, ISTATE_OFFSET_SP(\r)135 lw $at, EOFFSET_AT(\r) 136 lw $sp, EOFFSET_SP(\r) 209 137 .endm 210 138 211 /* 212 * Move kernel stack pointer address to register $k0. 213 * If we are in user mode, load the appropriate stack address. 214 */ 139 # Move kernel stack pointer address to register K0 140 # - if we are in user mode, load the appropriate stack 141 # address 215 142 .macro KERNEL_STACK_TO_K0 216 /* if we are in user mode */143 # If we are in user mode 217 144 mfc0 $k0, $status 218 145 andi $k0, 0x10 219 146 220 147 beq $k0, $0, 1f 221 move $k0, $sp222 223 /* move $k0 pointer to kernel stack */148 add $k0, $sp, 0 149 150 # Move $k0 pointer to kernel stack 224 151 lui $k0, %hi(supervisor_sp) 225 152 ori $k0, $k0, %lo(supervisor_sp) 226 227 /* move $k0 (supervisor_sp) */ 228 lw $k0, ($k0) 229 230 1: 153 # Move $k0 (superveisor_sp) 154 lw $k0, 0($k0) 155 1: 231 156 .endm 232 157 233 158 .org 0x0 234 159 kernel_image_start: 235 /* load temporary stack */160 /* Load temporary stack */ 236 161 lui $sp, %hi(end_stack) 237 162 ori $sp, $sp, %lo(end_stack) 238 163 239 /* not sure about this, but might be needed for PIC code */ 164 /* Not sure about this, but might 165 be needed for PIC code */ 240 166 lui $gp, 0x8000 241 167 242 168 /* $a1 contains physical address of bootinfo_t */ 169 243 170 jal arch_pre_main 244 171 nop … … 247 174 nop 248 175 249 .space TEMP_STACK_SIZE176 .space TEMP_STACK_SIZE 250 177 end_stack: 251 178 … … 262 189 nop 263 190 264 FAKE_ABI_PROLOGUE265 191 exception_handler: 266 192 KERNEL_STACK_TO_K0 267 268 sub $k0, ISTATE_SOFT_SIZE 269 sw $sp, ISTATE_OFFSET_SP($k0) 193 sub $k0, REGISTER_SPACE 194 sw $sp, EOFFSET_SP($k0) 270 195 move $sp, $k0 271 196 272 197 mfc0 $k0, $cause 273 198 274 sra $k0, $k0, 0x2 /* cp0_exc_cause() part 1 */275 andi $k0, $k0, 0x1f /* cp0_exc_cause() part 2 */276 sub $k0, 8 /* 8 = SYSCALL */199 sra $k0, $k0, 0x2 # cp0_exc_cause() part 1 200 andi $k0, $k0, 0x1f # cp0_exc_cause() part 2 201 sub $k0, 8 # 8 = SYSCALL 277 202 278 203 beqz $k0, syscall_shortcut 279 add $k0, 8 /* revert $k0 back to correct exc number */204 add $k0, 8 # Revert $k0 back to correct exc number 280 205 281 206 REGISTERS_STORE_AND_EXC_RESET $sp 282 207 283 208 move $a1, $sp 284 jal exc_dispatch /* exc_dispatch(excno, register_space) */209 jal exc_dispatch # exc_dispatch(excno, register_space) 285 210 move $a0, $k0 286 211 287 212 REGISTERS_LOAD $sp 288 /* the $sp is automatically restored to former value */ 289 eret 290 291 /** Syscall entry 292 * 293 * Registers: 294 * 295 * @param $v0 Syscall number. 296 * @param $a0 1st argument. 297 * @param $a1 2nd argument. 298 * @param $a2 3rd argument. 299 * @param $a3 4th argument. 300 * @param $t0 5th argument. 301 * @param $t1 6th argument. 302 * 303 * @return The return value will be stored in $v0. 304 * 305 */ 213 # The $sp is automatically restored to former value 214 eret 215 216 ## Syscall entry 217 # 218 # Registers: 219 # 220 # @param v0 Syscall number. 221 # @param a0 1st argument. 222 # @param a1 2nd argument. 223 # @param a2 3rd argument. 224 # @param a3 4th argument. 225 # @param t0 5th argument. 226 # @param t1 6th argument. 227 # 228 # @return The return value will be stored in v0. 229 # 230 #define SS_SP EOFFSET_SP 231 #define SS_STATUS EOFFSET_STATUS 232 #define SS_EPC EOFFSET_EPC 233 #define SS_K1 EOFFSET_K1 306 234 syscall_shortcut: 235 # We have a lot of space on the stack, with free use 307 236 mfc0 $t3, $epc 308 237 mfc0 $t2, $status 309 sw $t3, ISTATE_OFFSET_EPC($sp) /* save EPC */310 sw $k1, ISTATE_OFFSET_KT1($sp) /* save $k1 not saved on context switch */311 312 and $t4, $t2, REG_SAVE_MASK /* save only KSU, EXL, ERL, IE */238 sw $t3, SS_EPC($sp) # Save EPC 239 sw $k1, SS_K1($sp) # Save k1 not saved on context switch 240 241 and $t4, $t2, REG_SAVE_MASK # Save only KSU, EXL, ERL, IE 313 242 li $t5, ~(0x1f) 314 and $t2, $t2, $t5 /* clear KSU, EXL, ERL */315 ori $t2, $t2, 0x1 /* set IE */316 317 sw $t4, ISTATE_OFFSET_STATUS($sp)243 and $t2, $t2, $t5 # Clear KSU, EXL, ERL 244 ori $t2, $t2, 0x1 # Set IE 245 246 sw $t4, SS_STATUS($sp) 318 247 mtc0 $t2, $status 319 320 /*321 * Call the higher level system call handler.322 *323 */324 sw $t0, ISTATE_OFFSET_T0($sp) /* save the 5th argument on the stack */325 sw $t1, ISTATE_OFFSET_T1($sp) /* save the 6th argument on the stack */248 249 # 250 # Call the higher level system call handler 251 # We are going to reuse part of the unused exception stack frame 252 # 253 sw $t0, STACK_ARG4($sp) # save the 5th argument on the stack 254 sw $t1, STACK_ARG5($sp) # save the 6th argument on the stack 326 255 jal syscall_handler 327 sw $v0, ISTATE_OFFSET_V0($sp) /* save the syscall number on the stack */328 329 /* restore status */256 sw $v0, STACK_ARG6($sp) # save the syscall number on the stack 257 258 # restore status 330 259 mfc0 $t2, $status 331 lw $t3, ISTATE_OFFSET_STATUS($sp) 332 333 /* 334 * Change back to EXL = 1 (from last exception), otherwise 335 * an interrupt could rewrite the CP0 - EPC. 336 * 337 */ 338 li $t4, ~REG_SAVE_MASK /* mask UM, EXL, ERL, IE */ 260 lw $t3, SS_STATUS($sp) 261 262 # Change back to EXL = 1 (from last exception), otherwise 263 # an interrupt could rewrite the CP0 - EPC 264 li $t4, ~REG_SAVE_MASK # Mask UM, EXL, ERL, IE 339 265 and $t2, $t2, $t4 340 or $t2, $t2, $t3 /* copy saved UM, EXL, ERL, IE */266 or $t2, $t2, $t3 # Copy saved UM, EXL, ERL, IE 341 267 mtc0 $t2, $status 342 343 /* restore epc + 4 */344 lw $t2, ISTATE_OFFSET_EPC($sp)345 lw $k1, ISTATE_OFFSET_KT1($sp)268 269 # restore epc + 4 270 lw $t2, SS_EPC($sp) 271 lw $k1, SS_K1($sp) 346 272 addi $t2, $t2, 4 347 273 mtc0 $t2, $epc 348 274 349 lw $sp, ISTATE_OFFSET_SP($sp) /* restore $sp */350 eret351 352 FAKE_ABI_PROLOGUE275 lw $sp, SS_SP($sp) # restore sp 276 277 eret 278 353 279 tlb_refill_handler: 354 280 KERNEL_STACK_TO_K0 355 sub $k0, ISTATE_SOFT_SIZE281 sub $k0, REGISTER_SPACE 356 282 REGISTERS_STORE_AND_EXC_RESET $k0 357 sw $sp, ISTATE_OFFSET_SP($k0)358 move $sp, $k0359 283 sw $sp,EOFFSET_SP($k0) 284 add $sp, $k0, 0 285 360 286 jal tlb_refill 361 move $a0, $sp362 287 add $a0, $sp, 0 288 363 289 REGISTERS_LOAD $sp 364 eret 365 366 FAKE_ABI_PROLOGUE 290 291 eret 292 367 293 cache_error_handler: 368 294 KERNEL_STACK_TO_K0 369 sub $k0, ISTATE_SOFT_SIZE295 sub $k0, REGISTER_SPACE 370 296 REGISTERS_STORE_AND_EXC_RESET $k0 371 sw $sp, ISTATE_OFFSET_SP($k0)372 move $sp, $k0373 297 sw $sp,EOFFSET_SP($k0) 298 add $sp, $k0, 0 299 374 300 jal cache_error 375 move $a0, $sp376 301 add $a0, $sp, 0 302 377 303 REGISTERS_LOAD $sp 304 378 305 eret 379 306 380 307 userspace_asm: 381 move $sp, $a0382 move $v0, $a1383 move $t9, $a2 /* set up correct entry into PIC code */384 xor $a0, $a0, $a0 /* $a0 is defined to hold pcb_ptr */385 /* set it to 0 */386 eret 308 add $sp, $a0, 0 309 add $v0, $a1, 0 310 add $t9, $a2, 0 # Set up correct entry into PIC code 311 xor $a0, $a0, $a0 # $a0 is defined to hold pcb_ptr 312 # set it to 0 313 eret
Note:
See TracChangeset
for help on using the changeset viewer.