-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
ARC: Process-creation/scheduling/idle-loop
Signed-off-by: Vineet Gupta <vgupta@synopsys.com> Cc: Al Viro <viro@ZenIV.linux.org.uk> Cc: Thomas Gleixner <tglx@linutronix.de>
- Loading branch information
Vineet Gupta
committed
Feb 11, 2013
1 parent
4adeefe
commit bf90e1e
Showing
10 changed files
with
484 additions
and
8 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
/* | ||
* Copyright (C) 2004, 2007-2010, 2011-2012 Synopsys, Inc. (www.synopsys.com) | ||
* | ||
* This program is free software; you can redistribute it and/or modify | ||
* it under the terms of the GNU General Public License version 2 as | ||
* published by the Free Software Foundation. | ||
*/ | ||
|
||
#ifndef _ASM_ARC_SWITCH_TO_H | ||
#define _ASM_ARC_SWITCH_TO_H | ||
|
||
#ifndef __ASSEMBLY__ | ||
|
||
#include <linux/sched.h> | ||
|
||
#ifdef CONFIG_ARC_FPU_SAVE_RESTORE | ||
|
||
extern void fpu_save_restore(struct task_struct *p, struct task_struct *n); | ||
#define ARC_FPU_PREV(p, n) fpu_save_restore(p, n) | ||
#define ARC_FPU_NEXT(t) | ||
|
||
#else | ||
|
||
#define ARC_FPU_PREV(p, n) | ||
#define ARC_FPU_NEXT(n) | ||
|
||
#endif /* !CONFIG_ARC_FPU_SAVE_RESTORE */ | ||
|
||
struct task_struct *__switch_to(struct task_struct *p, struct task_struct *n); | ||
|
||
#define switch_to(prev, next, last) \ | ||
do { \ | ||
ARC_FPU_PREV(prev, next); \ | ||
last = __switch_to(prev, next);\ | ||
ARC_FPU_NEXT(next); \ | ||
mb(); \ | ||
} while (0) | ||
|
||
#endif | ||
|
||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,91 @@ | ||
/* | ||
* Copyright (C) 2004, 2007-2010, 2011-2012 Synopsys, Inc. (www.synopsys.com) | ||
* | ||
* This program is free software; you can redistribute it and/or modify | ||
* it under the terms of the GNU General Public License version 2 as | ||
* published by the Free Software Foundation. | ||
* | ||
* Vineetg: Aug 2009 | ||
* -"C" version of lowest level context switch asm macro called by schedular | ||
* gcc doesn't generate the dward CFI info for hand written asm, hence can't | ||
* backtrace out of it (e.g. tasks sleeping in kernel). | ||
* So we cheat a bit by writing almost similar code in inline-asm. | ||
* -This is a hacky way of doing things, but there is no other simple way. | ||
* I don't want/intend to extend unwinding code to understand raw asm | ||
*/ | ||
|
||
#include <asm/asm-offsets.h> | ||
#include <linux/sched.h> | ||
|
||
struct task_struct *__sched | ||
__switch_to(struct task_struct *prev_task, struct task_struct *next_task) | ||
{ | ||
unsigned int tmp; | ||
unsigned int prev = (unsigned int)prev_task; | ||
unsigned int next = (unsigned int)next_task; | ||
int num_words_to_skip = 1; | ||
|
||
__asm__ __volatile__( | ||
/* FP/BLINK save generated by gcc (standard function prologue */ | ||
"st.a r13, [sp, -4] \n\t" | ||
"st.a r14, [sp, -4] \n\t" | ||
"st.a r15, [sp, -4] \n\t" | ||
"st.a r16, [sp, -4] \n\t" | ||
"st.a r17, [sp, -4] \n\t" | ||
"st.a r18, [sp, -4] \n\t" | ||
"st.a r19, [sp, -4] \n\t" | ||
"st.a r20, [sp, -4] \n\t" | ||
"st.a r21, [sp, -4] \n\t" | ||
"st.a r22, [sp, -4] \n\t" | ||
"st.a r23, [sp, -4] \n\t" | ||
"st.a r24, [sp, -4] \n\t" | ||
"st.a r25, [sp, -4] \n\t" | ||
"sub sp, sp, %4 \n\t" /* create gutter at top */ | ||
|
||
/* set ksp of outgoing task in tsk->thread.ksp */ | ||
"st.as sp, [%3, %1] \n\t" | ||
|
||
"sync \n\t" | ||
|
||
/* | ||
* setup _current_task with incoming tsk. | ||
* optionally, set r25 to that as well | ||
* For SMP extra work to get to &_current_task[cpu] | ||
* (open coded SET_CURR_TASK_ON_CPU) | ||
*/ | ||
"st %2, [@_current_task] \n\t" | ||
|
||
/* get ksp of incoming task from tsk->thread.ksp */ | ||
"ld.as sp, [%2, %1] \n\t" | ||
|
||
/* start loading it's CALLEE reg file */ | ||
|
||
"add sp, sp, %4 \n\t" /* skip gutter at top */ | ||
|
||
"ld.ab r25, [sp, 4] \n\t" | ||
"ld.ab r24, [sp, 4] \n\t" | ||
"ld.ab r23, [sp, 4] \n\t" | ||
"ld.ab r22, [sp, 4] \n\t" | ||
"ld.ab r21, [sp, 4] \n\t" | ||
"ld.ab r20, [sp, 4] \n\t" | ||
"ld.ab r19, [sp, 4] \n\t" | ||
"ld.ab r18, [sp, 4] \n\t" | ||
"ld.ab r17, [sp, 4] \n\t" | ||
"ld.ab r16, [sp, 4] \n\t" | ||
"ld.ab r15, [sp, 4] \n\t" | ||
"ld.ab r14, [sp, 4] \n\t" | ||
"ld.ab r13, [sp, 4] \n\t" | ||
|
||
/* last (ret value) = prev : although for ARC it mov r0, r0 */ | ||
"mov %0, %3 \n\t" | ||
|
||
/* FP/BLINK restore generated by gcc (standard func epilogue */ | ||
|
||
: "=r"(tmp) | ||
: "n"((TASK_THREAD + THREAD_KSP) / 4), "r"(next), "r"(prev), | ||
"n"(num_words_to_skip * 4) | ||
: "blink" | ||
); | ||
|
||
return (struct task_struct *)tmp; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
/* | ||
* Copyright (C) 2004, 2007-2010, 2011-2012 Synopsys, Inc. (www.synopsys.com) | ||
* | ||
* This program is free software; you can redistribute it and/or modify | ||
* it under the terms of the GNU General Public License version 2 as | ||
* published by the Free Software Foundation. | ||
* | ||
* Vineetg: Aug 2009 | ||
* -Moved core context switch macro out of entry.S into this file. | ||
* -This is the more "natural" hand written assembler | ||
*/ | ||
|
||
#include <asm/entry.h> /* For the SAVE_* macros */ | ||
#include <asm/asm-offsets.h> | ||
#include <asm/linkage.h> | ||
|
||
;################### Low Level Context Switch ########################## | ||
|
||
.section .sched.text,"ax",@progbits | ||
.align 4 | ||
.global __switch_to | ||
.type __switch_to, @function | ||
__switch_to: | ||
|
||
/* Save regs on kernel mode stack of task */ | ||
st.a blink, [sp, -4] | ||
st.a fp, [sp, -4] | ||
SAVE_CALLEE_SAVED_KERNEL | ||
|
||
/* Save the now KSP in task->thread.ksp */ | ||
st.as sp, [r0, (TASK_THREAD + THREAD_KSP)/4] | ||
|
||
/* | ||
* Return last task in r0 (return reg) | ||
* On ARC, Return reg = First Arg reg = r0. | ||
* Since we already have last task in r0, | ||
* don't need to do anything special to return it | ||
*/ | ||
|
||
/* hardware memory barrier */ | ||
sync | ||
|
||
/* | ||
* switch to new task, contained in r1 | ||
* Temp reg r3 is required to get the ptr to store val | ||
*/ | ||
SET_CURR_TASK_ON_CPU r1, r3 | ||
|
||
/* reload SP with kernel mode stack pointer in task->thread.ksp */ | ||
ld.as sp, [r1, (TASK_THREAD + THREAD_KSP)/4] | ||
|
||
/* restore the registers */ | ||
RESTORE_CALLEE_SAVED_KERNEL | ||
ld.ab fp, [sp, 4] | ||
ld.ab blink, [sp, 4] | ||
j [blink] | ||
|
||
ARC_EXIT __switch_to |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
/* | ||
* fpu.c - save/restore of Floating Point Unit Registers on task switch | ||
* | ||
* Copyright (C) 2004, 2007-2010, 2011-2012 Synopsys, Inc. (www.synopsys.com) | ||
* | ||
* This program is free software; you can redistribute it and/or modify | ||
* it under the terms of the GNU General Public License version 2 as | ||
* published by the Free Software Foundation. | ||
*/ | ||
|
||
#include <linux/sched.h> | ||
#include <asm/switch_to.h> | ||
|
||
/* | ||
* To save/restore FPU regs, simplest scheme would use LR/SR insns. | ||
* However since SR serializes the pipeline, an alternate "hack" can be used | ||
* which uses the FPU Exchange insn (DEXCL) to r/w FPU regs. | ||
* | ||
* Store to 64bit dpfp1 reg from a pair of core regs: | ||
* dexcl1 0, r1, r0 ; where r1:r0 is the 64 bit val | ||
* | ||
* Read from dpfp1 into pair of core regs (w/o clobbering dpfp1) | ||
* mov_s r3, 0 | ||
* daddh11 r1, r3, r3 ; get "hi" into r1 (dpfp1 unchanged) | ||
* dexcl1 r0, r1, r3 ; get "low" into r0 (dpfp1 low clobbered) | ||
* dexcl1 0, r1, r0 ; restore dpfp1 to orig value | ||
* | ||
* However we can tweak the read, so that read-out of outgoing task's FPU regs | ||
* and write of incoming task's regs happen in one shot. So all the work is | ||
* done before context switch | ||
*/ | ||
|
||
void fpu_save_restore(struct task_struct *prev, struct task_struct *next) | ||
{ | ||
unsigned int *saveto = &prev->thread.fpu.aux_dpfp[0].l; | ||
unsigned int *readfrom = &next->thread.fpu.aux_dpfp[0].l; | ||
|
||
const unsigned int zero = 0; | ||
|
||
__asm__ __volatile__( | ||
"daddh11 %0, %2, %2\n" | ||
"dexcl1 %1, %3, %4\n" | ||
: "=&r" (*(saveto + 1)), /* early clobber must here */ | ||
"=&r" (*(saveto)) | ||
: "r" (zero), "r" (*(readfrom + 1)), "r" (*(readfrom)) | ||
); | ||
|
||
__asm__ __volatile__( | ||
"daddh22 %0, %2, %2\n" | ||
"dexcl2 %1, %3, %4\n" | ||
: "=&r"(*(saveto + 3)), /* early clobber must here */ | ||
"=&r"(*(saveto + 2)) | ||
: "r" (zero), "r" (*(readfrom + 3)), "r" (*(readfrom + 2)) | ||
); | ||
} |
Oops, something went wrong.