Commit ad22c71c authored by David Howells's avatar David Howells Committed by Linus Torvalds

[PATCH] FRV: Make switch_to() return previous task

This makes switch_to() on the FRV pass through and return the previous
task pointer rather than trusting to luck that it'll be left in the
correct register/variable. 
Signed-Off-By: default avatarDavid Howells <dhowells@redhat.com>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 85714da1
...@@ -782,13 +782,12 @@ __entry_do_NMI: ...@@ -782,13 +782,12 @@ __entry_do_NMI:
############################################################################### ###############################################################################
# #
# the return path for a newly forked child process # the return path for a newly forked child process
# - __switch_to() saved the old current pointer in GR27 for us # - __switch_to() saved the old current pointer in GR8 for us
# #
############################################################################### ###############################################################################
.globl ret_from_fork .globl ret_from_fork
ret_from_fork: ret_from_fork:
LEDS 0x6100 LEDS 0x6100
ori.p gr27,0,gr8
call schedule_tail call schedule_tail
# fork & co. return 0 to child # fork & co. return 0 to child
......
...@@ -43,20 +43,22 @@ __kernel_current_task: ...@@ -43,20 +43,22 @@ __kernel_current_task:
############################################################################### ###############################################################################
# #
# struct task_struct *__switch_to(struct thread_struct *prev, struct thread_struct *next) # struct task_struct *__switch_to(struct thread_struct *prev_thread,
# struct thread_struct *next_thread,
# struct task_struct *prev)
# #
############################################################################### ###############################################################################
.globl __switch_to .globl __switch_to
__switch_to: __switch_to:
# save outgoing process's context # save outgoing process's context
sethi.p %hi(__switch_back),gr11 sethi.p %hi(__switch_back),gr13
setlo %lo(__switch_back),gr11 setlo %lo(__switch_back),gr13
movsg lr,gr10 movsg lr,gr12
stdi gr28,@(gr8,#__THREAD_FRAME) stdi gr28,@(gr8,#__THREAD_FRAME)
sti sp ,@(gr8,#__THREAD_SP) sti sp ,@(gr8,#__THREAD_SP)
sti fp ,@(gr8,#__THREAD_FP) sti fp ,@(gr8,#__THREAD_FP)
stdi gr10,@(gr8,#__THREAD_LR) stdi gr12,@(gr8,#__THREAD_LR)
stdi gr16,@(gr8,#__THREAD_GR(16)) stdi gr16,@(gr8,#__THREAD_GR(16))
stdi gr18,@(gr8,#__THREAD_GR(18)) stdi gr18,@(gr8,#__THREAD_GR(18))
stdi gr20,@(gr8,#__THREAD_GR(20)) stdi gr20,@(gr8,#__THREAD_GR(20))
...@@ -75,7 +77,7 @@ __switch_to: ...@@ -75,7 +77,7 @@ __switch_to:
movsg psr,gr4 movsg psr,gr4
lddi.p @(gr9,#__THREAD_FRAME),gr10 lddi.p @(gr9,#__THREAD_FRAME),gr10
or gr29,gr29,gr27 ; ret_from_fork needs to know old current or gr10,gr10,gr27 ; save prev for the return value
ldi @(gr11,#4),gr19 ; get new_current->thread_info ldi @(gr11,#4),gr19 ; get new_current->thread_info
...@@ -88,8 +90,8 @@ __switch_to: ...@@ -88,8 +90,8 @@ __switch_to:
andi gr4,#~PSR_ET,gr5 andi gr4,#~PSR_ET,gr5
movgs gr5,psr movgs gr5,psr
or.p gr10,gr0,gr28 or.p gr10,gr0,gr28 ; set __frame
or gr11,gr0,gr29 or gr11,gr0,gr29 ; set __current
or.p gr12,gr0,sp or.p gr12,gr0,sp
or gr13,gr0,fp or gr13,gr0,fp
or gr19,gr0,gr15 ; set __current_thread_info or gr19,gr0,gr15 ; set __current_thread_info
...@@ -108,14 +110,17 @@ __switch_to: ...@@ -108,14 +110,17 @@ __switch_to:
111: 111:
# jump to __switch_back or ret_from_fork as appropriate # jump to __switch_back or ret_from_fork as appropriate
# - move prev to GR8
movgs gr4,psr movgs gr4,psr
jmpl @(gr18,gr0) jmpl.p @(gr18,gr0)
or gr27,gr27,gr8
############################################################################### ###############################################################################
# #
# restore incoming process's context # restore incoming process's context
# - on entry: # - on entry:
# - SP, FP, LR, GR15, GR28 and GR29 will have been set up appropriately # - SP, FP, LR, GR15, GR28 and GR29 will have been set up appropriately
# - GR8 will point to the outgoing task_struct
# - GR9 will point to the incoming thread_struct # - GR9 will point to the incoming thread_struct
# #
############################################################################### ###############################################################################
...@@ -128,12 +133,16 @@ __switch_back: ...@@ -128,12 +133,16 @@ __switch_back:
lddi @(gr9,#__THREAD_GR(26)),gr26 lddi @(gr9,#__THREAD_GR(26)),gr26
# fall through into restore_user_regs() # fall through into restore_user_regs()
ldi @(gr9,#__THREAD_USER),gr8 ldi.p @(gr9,#__THREAD_USER),gr8
or gr8,gr8,gr9
############################################################################### ###############################################################################
# #
# restore extra general regs and FP/Media regs # restore extra general regs and FP/Media regs
# - void restore_user_regs(const struct user_context *target) # - void *restore_user_regs(const struct user_context *target, void *retval)
# - on entry:
# - GR8 will point to the user context to swap in
# - GR9 will contain the value to be returned in GR8 (prev task on context switch)
# #
############################################################################### ###############################################################################
.globl restore_user_regs .globl restore_user_regs
...@@ -245,6 +254,7 @@ __restore_skip_fr32_fr63: ...@@ -245,6 +254,7 @@ __restore_skip_fr32_fr63:
lddi @(gr8,#__FPMEDIA_FNER(0)),gr4 lddi @(gr8,#__FPMEDIA_FNER(0)),gr4
movsg fner0,gr4 movsg fner0,gr4
movsg fner1,gr5 movsg fner1,gr5
or.p gr9,gr9,gr8
bralr bralr
# the FR451 also has ACC8-11/ACCG8-11 regs (but not 4-7...) # the FR451 also has ACC8-11/ACCG8-11 regs (but not 4-7...)
......
...@@ -113,7 +113,7 @@ static inline void release_thread(struct task_struct *dead_task) ...@@ -113,7 +113,7 @@ static inline void release_thread(struct task_struct *dead_task)
extern asmlinkage int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags); extern asmlinkage int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags);
extern asmlinkage void save_user_regs(struct user_context *target); extern asmlinkage void save_user_regs(struct user_context *target);
extern asmlinkage void restore_user_regs(const struct user_context *target); extern asmlinkage void *restore_user_regs(const struct user_context *target, ...);
#define copy_segments(tsk, mm) do { } while (0) #define copy_segments(tsk, mm) do { } while (0)
#define release_segments(mm) do { } while (0) #define release_segments(mm) do { } while (0)
......
...@@ -26,12 +26,15 @@ struct thread_struct; ...@@ -26,12 +26,15 @@ struct thread_struct;
* The `mb' is to tell GCC not to cache `current' across this call. * The `mb' is to tell GCC not to cache `current' across this call.
*/ */
extern asmlinkage extern asmlinkage
void __switch_to(struct thread_struct *prev, struct thread_struct *next); struct task_struct *__switch_to(struct thread_struct *prev_thread,
struct thread_struct *next_thread,
struct task_struct *prev);
#define switch_to(prev, next, last) \ #define switch_to(prev, next, last) \
do { \ do { \
prev->thread.sched_lr = (unsigned long) __builtin_return_address(0); \ (prev)->thread.sched_lr = \
__switch_to(&prev->thread, &next->thread); \ (unsigned long) __builtin_return_address(0); \
(last) = __switch_to(&(prev)->thread, &(next)->thread, (prev)); \
mb(); \ mb(); \
} while(0) } while(0)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment