diff options
Diffstat (limited to 'arch/microblaze/kernel/entry.S')
-rw-r--r-- | arch/microblaze/kernel/entry.S | 46 |
1 files changed, 39 insertions, 7 deletions
diff --git a/arch/microblaze/kernel/entry.S b/arch/microblaze/kernel/entry.S index 819238b8a429..41c30cdb2704 100644 --- a/arch/microblaze/kernel/entry.S +++ b/arch/microblaze/kernel/entry.S | |||
@@ -287,25 +287,44 @@ | |||
287 | * are masked. This is nice, means we don't have to CLI before state save | 287 | * are masked. This is nice, means we don't have to CLI before state save |
288 | */ | 288 | */ |
289 | C_ENTRY(_user_exception): | 289 | C_ENTRY(_user_exception): |
290 | addi r14, r14, 4 /* return address is 4 byte after call */ | ||
291 | swi r1, r0, TOPHYS(PER_CPU(ENTRY_SP)) /* save stack */ | 290 | swi r1, r0, TOPHYS(PER_CPU(ENTRY_SP)) /* save stack */ |
291 | addi r14, r14, 4 /* return address is 4 byte after call */ | ||
292 | |||
293 | mfs r1, rmsr | ||
294 | nop | ||
295 | andi r1, r1, MSR_UMS | ||
296 | bnei r1, 1f | ||
297 | |||
298 | /* Kernel-mode state save - kernel execve */ | ||
299 | lwi r1, r0, TOPHYS(PER_CPU(ENTRY_SP)); /* Reload kernel stack-ptr*/ | ||
300 | tophys(r1,r1); | ||
301 | |||
302 | addik r1, r1, -STATE_SAVE_SIZE; /* Make room on the stack. */ | ||
303 | SAVE_REGS | ||
292 | 304 | ||
305 | swi r1, r1, PTO + PT_MODE; /* pt_regs -> kernel mode */ | ||
306 | brid 2f; | ||
307 | nop; /* Fill delay slot */ | ||
308 | |||
309 | /* User-mode state save. */ | ||
310 | 1: | ||
293 | lwi r1, r0, TOPHYS(PER_CPU(CURRENT_SAVE)); /* get saved current */ | 311 | lwi r1, r0, TOPHYS(PER_CPU(CURRENT_SAVE)); /* get saved current */ |
294 | tophys(r1,r1); | 312 | tophys(r1,r1); |
295 | lwi r1, r1, TS_THREAD_INFO; /* get stack from task_struct */ | 313 | lwi r1, r1, TS_THREAD_INFO; /* get stack from task_struct */ |
296 | /* MS these three instructions can be added to one */ | 314 | /* calculate kernel stack pointer from task struct 8k */ |
297 | /* addik r1, r1, THREAD_SIZE; */ | 315 | addik r1, r1, THREAD_SIZE; |
298 | /* tophys(r1,r1); */ | 316 | tophys(r1,r1); |
299 | /* addik r1, r1, -STATE_SAVE_SIZE; */ | 317 | |
300 | addik r1, r1, THREAD_SIZE + CONFIG_KERNEL_BASE_ADDR - CONFIG_KERNEL_START - STATE_SAVE_SIZE; | 318 | addik r1, r1, -STATE_SAVE_SIZE; /* Make room on the stack. */ |
301 | SAVE_REGS | 319 | SAVE_REGS |
302 | swi r0, r1, PTO + PT_R3 | 320 | swi r0, r1, PTO + PT_R3 |
303 | swi r0, r1, PTO + PT_R4 | 321 | swi r0, r1, PTO + PT_R4 |
304 | 322 | ||
323 | swi r0, r1, PTO + PT_MODE; /* Was in user-mode. */ | ||
305 | lwi r11, r0, TOPHYS(PER_CPU(ENTRY_SP)); | 324 | lwi r11, r0, TOPHYS(PER_CPU(ENTRY_SP)); |
306 | swi r11, r1, PTO+PT_R1; /* Store user SP. */ | 325 | swi r11, r1, PTO+PT_R1; /* Store user SP. */ |
307 | clear_ums; | 326 | clear_ums; |
308 | lwi CURRENT_TASK, r0, TOPHYS(PER_CPU(CURRENT_SAVE)); | 327 | 2: lwi CURRENT_TASK, r0, TOPHYS(PER_CPU(CURRENT_SAVE)); |
309 | /* Save away the syscall number. */ | 328 | /* Save away the syscall number. */ |
310 | swi r12, r1, PTO+PT_R0; | 329 | swi r12, r1, PTO+PT_R0; |
311 | tovirt(r1,r1) | 330 | tovirt(r1,r1) |
@@ -375,6 +394,9 @@ C_ENTRY(ret_from_trap): | |||
375 | swi r3, r1, PTO + PT_R3 | 394 | swi r3, r1, PTO + PT_R3 |
376 | swi r4, r1, PTO + PT_R4 | 395 | swi r4, r1, PTO + PT_R4 |
377 | 396 | ||
397 | lwi r11, r1, PTO + PT_MODE; | ||
398 | /* See if returning to kernel mode, if so, skip resched &c. */ | ||
399 | bnei r11, 2f; | ||
378 | /* We're returning to user mode, so check for various conditions that | 400 | /* We're returning to user mode, so check for various conditions that |
379 | * trigger rescheduling. */ | 401 | * trigger rescheduling. */ |
380 | /* FIXME: Restructure all these flag checks. */ | 402 | /* FIXME: Restructure all these flag checks. */ |
@@ -417,6 +439,16 @@ C_ENTRY(ret_from_trap): | |||
417 | RESTORE_REGS; | 439 | RESTORE_REGS; |
418 | addik r1, r1, STATE_SAVE_SIZE /* Clean up stack space. */ | 440 | addik r1, r1, STATE_SAVE_SIZE /* Clean up stack space. */ |
419 | lwi r1, r1, PT_R1 - PT_SIZE;/* Restore user stack pointer. */ | 441 | lwi r1, r1, PT_R1 - PT_SIZE;/* Restore user stack pointer. */ |
442 | bri 6f; | ||
443 | |||
444 | /* Return to kernel state. */ | ||
445 | 2: set_bip; /* Ints masked for state restore */ | ||
446 | VM_OFF; | ||
447 | tophys(r1,r1); | ||
448 | RESTORE_REGS; | ||
449 | addik r1, r1, STATE_SAVE_SIZE /* Clean up stack space. */ | ||
450 | tovirt(r1,r1); | ||
451 | 6: | ||
420 | TRAP_return: /* Make global symbol for debugging */ | 452 | TRAP_return: /* Make global symbol for debugging */ |
421 | rtbd r14, 0; /* Instructions to return from an IRQ */ | 453 | rtbd r14, 0; /* Instructions to return from an IRQ */ |
422 | nop; | 454 | nop; |