diff options
author | Vineet Gupta <vgupta@synopsys.com> | 2013-11-01 01:16:40 -0400 |
---|---|---|
committer | Vineet Gupta <vgupta@synopsys.com> | 2013-11-06 00:11:46 -0500 |
commit | 57e26e57454fae4f1d15c2e9fa965b7a8046ab34 (patch) | |
tree | 8100ec071f56fbd4cd3a01747ce971235118f6f3 /arch/arc | |
parent | 3aa4f80e410b3c14d987c42a90c31023c3081b46 (diff) |
ARC: [SMP] Fix build failures for large NR_CPUS
ST.as only takes S9 (255) for offset. This was going out of range when
accessing a task_struct field with 4k NR_CPUS (due to 128b of coumaks
itself in there).
Workaround by using an intermediate register to do the address scaling.
There is some duplication of fix for ctx_sw.c and ctx_sw_asm.S however
given that C version will go away soon I'm not bothering to factor out
the common code.
Reported-by: Noam Camus <noamc@ezchip.com>
Signed-off-by: Vineet Gupta <vgupta@synopsys.com>
Diffstat (limited to 'arch/arc')
-rw-r--r-- | arch/arc/kernel/ctx_sw.c | 13 | ||||
-rw-r--r-- | arch/arc/kernel/ctx_sw_asm.S | 11 |
2 files changed, 21 insertions, 3 deletions
diff --git a/arch/arc/kernel/ctx_sw.c b/arch/arc/kernel/ctx_sw.c index 34410eb1a308..c14a5bea0c76 100644 --- a/arch/arc/kernel/ctx_sw.c +++ b/arch/arc/kernel/ctx_sw.c | |||
@@ -17,6 +17,8 @@ | |||
17 | #include <asm/asm-offsets.h> | 17 | #include <asm/asm-offsets.h> |
18 | #include <linux/sched.h> | 18 | #include <linux/sched.h> |
19 | 19 | ||
20 | #define KSP_WORD_OFF ((TASK_THREAD + THREAD_KSP) / 4) | ||
21 | |||
20 | struct task_struct *__sched | 22 | struct task_struct *__sched |
21 | __switch_to(struct task_struct *prev_task, struct task_struct *next_task) | 23 | __switch_to(struct task_struct *prev_task, struct task_struct *next_task) |
22 | { | 24 | { |
@@ -45,7 +47,16 @@ __switch_to(struct task_struct *prev_task, struct task_struct *next_task) | |||
45 | #endif | 47 | #endif |
46 | 48 | ||
47 | /* set ksp of outgoing task in tsk->thread.ksp */ | 49 | /* set ksp of outgoing task in tsk->thread.ksp */ |
50 | #if KSP_WORD_OFF <= 255 | ||
48 | "st.as sp, [%3, %1] \n\t" | 51 | "st.as sp, [%3, %1] \n\t" |
52 | #else | ||
53 | /* | ||
54 | * Workaround for NR_CPUS=4k | ||
55 | * %1 is bigger than 255 (S9 offset for st.as) | ||
56 | */ | ||
57 | "add2 r24, %3, %1 \n\t" | ||
58 | "st sp, [r24] \n\t" | ||
59 | #endif | ||
49 | 60 | ||
50 | "sync \n\t" | 61 | "sync \n\t" |
51 | 62 | ||
@@ -97,7 +108,7 @@ __switch_to(struct task_struct *prev_task, struct task_struct *next_task) | |||
97 | /* FP/BLINK restore generated by gcc (standard func epilogue */ | 108 | /* FP/BLINK restore generated by gcc (standard func epilogue */ |
98 | 109 | ||
99 | : "=r"(tmp) | 110 | : "=r"(tmp) |
100 | : "n"((TASK_THREAD + THREAD_KSP) / 4), "r"(next), "r"(prev) | 111 | : "n"(KSP_WORD_OFF), "r"(next), "r"(prev) |
101 | : "blink" | 112 | : "blink" |
102 | ); | 113 | ); |
103 | 114 | ||
diff --git a/arch/arc/kernel/ctx_sw_asm.S b/arch/arc/kernel/ctx_sw_asm.S index d8972345e4c2..65690e7fcc8c 100644 --- a/arch/arc/kernel/ctx_sw_asm.S +++ b/arch/arc/kernel/ctx_sw_asm.S | |||
@@ -14,6 +14,8 @@ | |||
14 | #include <asm/asm-offsets.h> | 14 | #include <asm/asm-offsets.h> |
15 | #include <asm/linkage.h> | 15 | #include <asm/linkage.h> |
16 | 16 | ||
17 | #define KSP_WORD_OFF ((TASK_THREAD + THREAD_KSP) / 4) | ||
18 | |||
17 | ;################### Low Level Context Switch ########################## | 19 | ;################### Low Level Context Switch ########################## |
18 | 20 | ||
19 | .section .sched.text,"ax",@progbits | 21 | .section .sched.text,"ax",@progbits |
@@ -28,8 +30,13 @@ __switch_to: | |||
28 | SAVE_CALLEE_SAVED_KERNEL | 30 | SAVE_CALLEE_SAVED_KERNEL |
29 | 31 | ||
30 | /* Save the now KSP in task->thread.ksp */ | 32 | /* Save the now KSP in task->thread.ksp */ |
31 | st.as sp, [r0, (TASK_THREAD + THREAD_KSP)/4] | 33 | #if KSP_WORD_OFF <= 255 |
32 | 34 | st.as sp, [r0, KSP_WORD_OFF] | |
35 | #else | ||
36 | /* Workaround for NR_CPUS=4k as ST.as can only take s9 offset */ | ||
37 | add2 r24, r0, KSP_WORD_OFF | ||
38 | st sp, [r24] | ||
39 | #endif | ||
33 | /* | 40 | /* |
34 | * Return last task in r0 (return reg) | 41 | * Return last task in r0 (return reg) |
35 | * On ARC, Return reg = First Arg reg = r0. | 42 | * On ARC, Return reg = First Arg reg = r0. |