diff options
author | Vineet Gupta <vgupta@synopsys.com> | 2013-02-11 09:22:57 -0500 |
---|---|---|
committer | Vineet Gupta <vgupta@synopsys.com> | 2013-02-15 12:45:58 -0500 |
commit | 080c37473eb671a037b3e9a315303851f0675be5 (patch) | |
tree | b407d85217f9c979eed57f2adb31bc3fb06a9c09 | |
parent | 8872e9e513eba636c8d4266fe667660f73cd66e6 (diff) |
ARC: [optim] Cache "current" in Register r25
Signed-off-by: Vineet Gupta <vgupta@synopsys.com>
-rw-r--r-- | arch/arc/Kconfig | 7 | ||||
-rw-r--r-- | arch/arc/Makefile | 9 | ||||
-rw-r--r-- | arch/arc/include/asm/Kbuild | 1 | ||||
-rw-r--r-- | arch/arc/include/asm/current.h | 32 | ||||
-rw-r--r-- | arch/arc/include/asm/entry.h | 45 | ||||
-rw-r--r-- | arch/arc/include/asm/processor.h | 3 | ||||
-rw-r--r-- | arch/arc/kernel/asm-offsets.c | 3 | ||||
-rw-r--r-- | arch/arc/kernel/ctx_sw.c | 7 | ||||
-rw-r--r-- | arch/arc/kernel/entry.S | 14 |
9 files changed, 120 insertions, 1 deletions
diff --git a/arch/arc/Kconfig b/arch/arc/Kconfig index 7db978570fb8..03347cbde9bd 100644 --- a/arch/arc/Kconfig +++ b/arch/arc/Kconfig | |||
@@ -264,6 +264,13 @@ config LINUX_LINK_BASE | |||
264 | 264 | ||
265 | endmenu # "Platform Board Configuration" | 265 | endmenu # "Platform Board Configuration" |
266 | 266 | ||
267 | config ARC_CURR_IN_REG | ||
268 | bool "Dedicate Register r25 for current_task pointer" | ||
269 | default y | ||
270 | help | ||
271 | This reserved Register R25 to point to Current Task in | ||
272 | kernel mode. This saves memory access for each such access | ||
273 | |||
267 | config ARC_STACK_NONEXEC | 274 | config ARC_STACK_NONEXEC |
268 | bool "Make stack non-executable" | 275 | bool "Make stack non-executable" |
269 | default n | 276 | default n |
diff --git a/arch/arc/Makefile b/arch/arc/Makefile index 29b5fcd9c4b6..5c98fc19d99d 100644 --- a/arch/arc/Makefile +++ b/arch/arc/Makefile | |||
@@ -20,6 +20,15 @@ export PLATFORM | |||
20 | cflags-y += -Iarch/arc/plat-$(PLATFORM)/include | 20 | cflags-y += -Iarch/arc/plat-$(PLATFORM)/include |
21 | cflags-y += -mA7 -fno-common -pipe -fno-builtin -D__linux__ | 21 | cflags-y += -mA7 -fno-common -pipe -fno-builtin -D__linux__ |
22 | 22 | ||
23 | ifdef CONFIG_ARC_CURR_IN_REG | ||
24 | # For a global register defintion, make sure it gets passed to every file | ||
25 | # We had a customer reported bug where some code built in kernel was NOT using | ||
26 | # any kernel headers, and missing the r25 global register | ||
27 | # Can't do unconditionally (like above) because of recursive include issues | ||
28 | # due to <linux/thread_info.h> | ||
29 | LINUXINCLUDE += -include ${src}/arch/arc/include/asm/current.h | ||
30 | endif | ||
31 | |||
23 | atleast_gcc44 := $(call cc-ifversion, -gt, 0402, y) | 32 | atleast_gcc44 := $(call cc-ifversion, -gt, 0402, y) |
24 | cflags-$(atleast_gcc44) += -fsection-anchors | 33 | cflags-$(atleast_gcc44) += -fsection-anchors |
25 | 34 | ||
diff --git a/arch/arc/include/asm/Kbuild b/arch/arc/include/asm/Kbuild index 105ec1188aaf..78e982dad537 100644 --- a/arch/arc/include/asm/Kbuild +++ b/arch/arc/include/asm/Kbuild | |||
@@ -11,7 +11,6 @@ generic-y += bugs.h | |||
11 | generic-y += bitsperlong.h | 11 | generic-y += bitsperlong.h |
12 | generic-y += clkdev.h | 12 | generic-y += clkdev.h |
13 | generic-y += cputime.h | 13 | generic-y += cputime.h |
14 | generic-y += current.h | ||
15 | generic-y += device.h | 14 | generic-y += device.h |
16 | generic-y += div64.h | 15 | generic-y += div64.h |
17 | generic-y += emergency-restart.h | 16 | generic-y += emergency-restart.h |
diff --git a/arch/arc/include/asm/current.h b/arch/arc/include/asm/current.h new file mode 100644 index 000000000000..87b918585c4a --- /dev/null +++ b/arch/arc/include/asm/current.h | |||
@@ -0,0 +1,32 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2004, 2007-2010, 2011-2012 Synopsys, Inc. (www.synopsys.com) | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License version 2 as | ||
6 | * published by the Free Software Foundation. | ||
7 | * | ||
8 | * Vineetg: May 16th, 2008 | ||
9 | * - Current macro is now implemented as "global register" r25 | ||
10 | */ | ||
11 | |||
12 | #ifndef _ASM_ARC_CURRENT_H | ||
13 | #define _ASM_ARC_CURRENT_H | ||
14 | |||
15 | #ifdef __KERNEL__ | ||
16 | |||
17 | #ifndef __ASSEMBLY__ | ||
18 | |||
19 | #ifdef CONFIG_ARC_CURR_IN_REG | ||
20 | |||
21 | register struct task_struct *curr_arc asm("r25"); | ||
22 | #define current (curr_arc) | ||
23 | |||
24 | #else | ||
25 | #include <asm-generic/current.h> | ||
26 | #endif /* ! CONFIG_ARC_CURR_IN_REG */ | ||
27 | |||
28 | #endif /* ! __ASSEMBLY__ */ | ||
29 | |||
30 | #endif /* __KERNEL__ */ | ||
31 | |||
32 | #endif /* _ASM_ARC_CURRENT_H */ | ||
diff --git a/arch/arc/include/asm/entry.h b/arch/arc/include/asm/entry.h index 9eada5b28be6..716f4f7b5cd2 100644 --- a/arch/arc/include/asm/entry.h +++ b/arch/arc/include/asm/entry.h | |||
@@ -13,6 +13,8 @@ | |||
13 | * was being "CLEARED" rather then "SET". Actually "SET" clears ZOL context | 13 | * was being "CLEARED" rather then "SET". Actually "SET" clears ZOL context |
14 | * | 14 | * |
15 | * Vineetg: May 5th 2008 | 15 | * Vineetg: May 5th 2008 |
16 | * -Modified CALLEE_REG save/restore macros to handle the fact that | ||
17 | * r25 contains the kernel current task ptr | ||
16 | * - Defined Stack Switching Macro to be reused in all intr/excp hdlrs | 18 | * - Defined Stack Switching Macro to be reused in all intr/excp hdlrs |
17 | * - Shaved off 11 instructions from RESTORE_ALL_INT1 by using the | 19 | * - Shaved off 11 instructions from RESTORE_ALL_INT1 by using the |
18 | * address Write back load ld.ab instead of seperate ld/add instn | 20 | * address Write back load ld.ab instead of seperate ld/add instn |
@@ -28,6 +30,7 @@ | |||
28 | #include <asm/asm-offsets.h> | 30 | #include <asm/asm-offsets.h> |
29 | #include <asm/arcregs.h> | 31 | #include <asm/arcregs.h> |
30 | #include <asm/ptrace.h> | 32 | #include <asm/ptrace.h> |
33 | #include <asm/processor.h> /* For VMALLOC_START */ | ||
31 | #include <asm/thread_info.h> /* For THREAD_SIZE */ | 34 | #include <asm/thread_info.h> /* For THREAD_SIZE */ |
32 | 35 | ||
33 | /* Note on the LD/ST addr modes with addr reg wback | 36 | /* Note on the LD/ST addr modes with addr reg wback |
@@ -106,7 +109,14 @@ | |||
106 | st.a r22, [sp, -4] | 109 | st.a r22, [sp, -4] |
107 | st.a r23, [sp, -4] | 110 | st.a r23, [sp, -4] |
108 | st.a r24, [sp, -4] | 111 | st.a r24, [sp, -4] |
112 | |||
113 | #ifdef CONFIG_ARC_CURR_IN_REG | ||
114 | ; Retrieve orig r25 and save it on stack | ||
115 | ld r12, [r25, TASK_THREAD + THREAD_USER_R25] | ||
116 | st.a r12, [sp, -4] | ||
117 | #else | ||
109 | st.a r25, [sp, -4] | 118 | st.a r25, [sp, -4] |
119 | #endif | ||
110 | 120 | ||
111 | /* move up by 1 word to "create" callee_regs->"stack_place_holder" */ | 121 | /* move up by 1 word to "create" callee_regs->"stack_place_holder" */ |
112 | sub sp, sp, 4 | 122 | sub sp, sp, 4 |
@@ -131,8 +141,12 @@ | |||
131 | st.a r22, [sp, -4] | 141 | st.a r22, [sp, -4] |
132 | st.a r23, [sp, -4] | 142 | st.a r23, [sp, -4] |
133 | st.a r24, [sp, -4] | 143 | st.a r24, [sp, -4] |
144 | #ifdef CONFIG_ARC_CURR_IN_REG | ||
145 | sub sp, sp, 8 | ||
146 | #else | ||
134 | st.a r25, [sp, -4] | 147 | st.a r25, [sp, -4] |
135 | sub sp, sp, 4 | 148 | sub sp, sp, 4 |
149 | #endif | ||
136 | .endm | 150 | .endm |
137 | 151 | ||
138 | /*-------------------------------------------------------------- | 152 | /*-------------------------------------------------------------- |
@@ -148,8 +162,14 @@ | |||
148 | *-------------------------------------------------------------*/ | 162 | *-------------------------------------------------------------*/ |
149 | .macro RESTORE_CALLEE_SAVED_KERNEL | 163 | .macro RESTORE_CALLEE_SAVED_KERNEL |
150 | 164 | ||
165 | |||
166 | #ifdef CONFIG_ARC_CURR_IN_REG | ||
167 | add sp, sp, 8 /* skip callee_reg gutter and user r25 placeholder */ | ||
168 | #else | ||
151 | add sp, sp, 4 /* skip "callee_regs->stack_place_holder" */ | 169 | add sp, sp, 4 /* skip "callee_regs->stack_place_holder" */ |
152 | ld.ab r25, [sp, 4] | 170 | ld.ab r25, [sp, 4] |
171 | #endif | ||
172 | |||
153 | ld.ab r24, [sp, 4] | 173 | ld.ab r24, [sp, 4] |
154 | ld.ab r23, [sp, 4] | 174 | ld.ab r23, [sp, 4] |
155 | ld.ab r22, [sp, 4] | 175 | ld.ab r22, [sp, 4] |
@@ -235,6 +255,7 @@ | |||
235 | * | 255 | * |
236 | * Entry : r9 contains pre-IRQ/exception/trap status32 | 256 | * Entry : r9 contains pre-IRQ/exception/trap status32 |
237 | * Exit : SP is set to kernel mode stack pointer | 257 | * Exit : SP is set to kernel mode stack pointer |
258 | * If CURR_IN_REG, r25 set to "current" task pointer | ||
238 | * Clobbers: r9 | 259 | * Clobbers: r9 |
239 | *-------------------------------------------------------------*/ | 260 | *-------------------------------------------------------------*/ |
240 | 261 | ||
@@ -259,6 +280,16 @@ | |||
259 | 280 | ||
260 | GET_CURR_TASK_ON_CPU r9 | 281 | GET_CURR_TASK_ON_CPU r9 |
261 | 282 | ||
283 | #ifdef CONFIG_ARC_CURR_IN_REG | ||
284 | |||
285 | /* If current task pointer cached in r25, time to | ||
286 | * -safekeep USER r25 in task->thread_struct->user_r25 | ||
287 | * -load r25 with current task ptr | ||
288 | */ | ||
289 | st.as r25, [r9, (TASK_THREAD + THREAD_USER_R25)/4] | ||
290 | mov r25, r9 | ||
291 | #endif | ||
292 | |||
262 | /* With current tsk in r9, get it's kernel mode stack base */ | 293 | /* With current tsk in r9, get it's kernel mode stack base */ |
263 | GET_TSK_STACK_BASE r9, r9 | 294 | GET_TSK_STACK_BASE r9, r9 |
264 | 295 | ||
@@ -519,17 +550,31 @@ | |||
519 | 550 | ||
520 | .macro SET_CURR_TASK_ON_CPU tsk, tmp | 551 | .macro SET_CURR_TASK_ON_CPU tsk, tmp |
521 | st \tsk, [@_current_task] | 552 | st \tsk, [@_current_task] |
553 | #ifdef CONFIG_ARC_CURR_IN_REG | ||
554 | mov r25, \tsk | ||
555 | #endif | ||
522 | .endm | 556 | .endm |
523 | 557 | ||
524 | /* ------------------------------------------------------------------ | 558 | /* ------------------------------------------------------------------ |
525 | * Get the ptr to some field of Current Task at @off in task struct | 559 | * Get the ptr to some field of Current Task at @off in task struct |
560 | * -Uses r25 for Current task ptr if that is enabled | ||
526 | */ | 561 | */ |
527 | 562 | ||
563 | #ifdef CONFIG_ARC_CURR_IN_REG | ||
564 | |||
565 | .macro GET_CURR_TASK_FIELD_PTR off, reg | ||
566 | add \reg, r25, \off | ||
567 | .endm | ||
568 | |||
569 | #else | ||
570 | |||
528 | .macro GET_CURR_TASK_FIELD_PTR off, reg | 571 | .macro GET_CURR_TASK_FIELD_PTR off, reg |
529 | GET_CURR_TASK_ON_CPU \reg | 572 | GET_CURR_TASK_ON_CPU \reg |
530 | add \reg, \reg, \off | 573 | add \reg, \reg, \off |
531 | .endm | 574 | .endm |
532 | 575 | ||
576 | #endif /* CONFIG_ARC_CURR_IN_REG */ | ||
577 | |||
533 | #endif /* __ASSEMBLY__ */ | 578 | #endif /* __ASSEMBLY__ */ |
534 | 579 | ||
535 | #endif /* __ASM_ARC_ENTRY_H */ | 580 | #endif /* __ASM_ARC_ENTRY_H */ |
diff --git a/arch/arc/include/asm/processor.h b/arch/arc/include/asm/processor.h index 860252ec3fa7..b7b155610067 100644 --- a/arch/arc/include/asm/processor.h +++ b/arch/arc/include/asm/processor.h | |||
@@ -29,6 +29,9 @@ struct thread_struct { | |||
29 | unsigned long callee_reg; /* pointer to callee regs */ | 29 | unsigned long callee_reg; /* pointer to callee regs */ |
30 | unsigned long fault_address; /* dbls as brkpt holder as well */ | 30 | unsigned long fault_address; /* dbls as brkpt holder as well */ |
31 | unsigned long cause_code; /* Exception Cause Code (ECR) */ | 31 | unsigned long cause_code; /* Exception Cause Code (ECR) */ |
32 | #ifdef CONFIG_ARC_CURR_IN_REG | ||
33 | unsigned long user_r25; | ||
34 | #endif | ||
32 | #ifdef CONFIG_ARC_FPU_SAVE_RESTORE | 35 | #ifdef CONFIG_ARC_FPU_SAVE_RESTORE |
33 | struct arc_fpu fpu; | 36 | struct arc_fpu fpu; |
34 | #endif | 37 | #endif |
diff --git a/arch/arc/kernel/asm-offsets.c b/arch/arc/kernel/asm-offsets.c index d7770cc9aee3..0dc148ebce74 100644 --- a/arch/arc/kernel/asm-offsets.c +++ b/arch/arc/kernel/asm-offsets.c | |||
@@ -24,6 +24,9 @@ int main(void) | |||
24 | 24 | ||
25 | DEFINE(THREAD_KSP, offsetof(struct thread_struct, ksp)); | 25 | DEFINE(THREAD_KSP, offsetof(struct thread_struct, ksp)); |
26 | DEFINE(THREAD_CALLEE_REG, offsetof(struct thread_struct, callee_reg)); | 26 | DEFINE(THREAD_CALLEE_REG, offsetof(struct thread_struct, callee_reg)); |
27 | #ifdef CONFIG_ARC_CURR_IN_REG | ||
28 | DEFINE(THREAD_USER_R25, offsetof(struct thread_struct, user_r25)); | ||
29 | #endif | ||
27 | DEFINE(THREAD_FAULT_ADDR, | 30 | DEFINE(THREAD_FAULT_ADDR, |
28 | offsetof(struct thread_struct, fault_address)); | 31 | offsetof(struct thread_struct, fault_address)); |
29 | 32 | ||
diff --git a/arch/arc/kernel/ctx_sw.c b/arch/arc/kernel/ctx_sw.c index 647e37a5165e..fbf739cbaf7d 100644 --- a/arch/arc/kernel/ctx_sw.c +++ b/arch/arc/kernel/ctx_sw.c | |||
@@ -24,6 +24,9 @@ __switch_to(struct task_struct *prev_task, struct task_struct *next_task) | |||
24 | unsigned int prev = (unsigned int)prev_task; | 24 | unsigned int prev = (unsigned int)prev_task; |
25 | unsigned int next = (unsigned int)next_task; | 25 | unsigned int next = (unsigned int)next_task; |
26 | int num_words_to_skip = 1; | 26 | int num_words_to_skip = 1; |
27 | #ifdef CONFIG_ARC_CURR_IN_REG | ||
28 | num_words_to_skip++; | ||
29 | #endif | ||
27 | 30 | ||
28 | __asm__ __volatile__( | 31 | __asm__ __volatile__( |
29 | /* FP/BLINK save generated by gcc (standard function prologue */ | 32 | /* FP/BLINK save generated by gcc (standard function prologue */ |
@@ -39,7 +42,9 @@ __switch_to(struct task_struct *prev_task, struct task_struct *next_task) | |||
39 | "st.a r22, [sp, -4] \n\t" | 42 | "st.a r22, [sp, -4] \n\t" |
40 | "st.a r23, [sp, -4] \n\t" | 43 | "st.a r23, [sp, -4] \n\t" |
41 | "st.a r24, [sp, -4] \n\t" | 44 | "st.a r24, [sp, -4] \n\t" |
45 | #ifndef CONFIG_ARC_CURR_IN_REG | ||
42 | "st.a r25, [sp, -4] \n\t" | 46 | "st.a r25, [sp, -4] \n\t" |
47 | #endif | ||
43 | "sub sp, sp, %4 \n\t" /* create gutter at top */ | 48 | "sub sp, sp, %4 \n\t" /* create gutter at top */ |
44 | 49 | ||
45 | /* set ksp of outgoing task in tsk->thread.ksp */ | 50 | /* set ksp of outgoing task in tsk->thread.ksp */ |
@@ -62,7 +67,9 @@ __switch_to(struct task_struct *prev_task, struct task_struct *next_task) | |||
62 | 67 | ||
63 | "add sp, sp, %4 \n\t" /* skip gutter at top */ | 68 | "add sp, sp, %4 \n\t" /* skip gutter at top */ |
64 | 69 | ||
70 | #ifndef CONFIG_ARC_CURR_IN_REG | ||
65 | "ld.ab r25, [sp, 4] \n\t" | 71 | "ld.ab r25, [sp, 4] \n\t" |
72 | #endif | ||
66 | "ld.ab r24, [sp, 4] \n\t" | 73 | "ld.ab r24, [sp, 4] \n\t" |
67 | "ld.ab r23, [sp, 4] \n\t" | 74 | "ld.ab r23, [sp, 4] \n\t" |
68 | "ld.ab r22, [sp, 4] \n\t" | 75 | "ld.ab r22, [sp, 4] \n\t" |
diff --git a/arch/arc/kernel/entry.S b/arch/arc/kernel/entry.S index ce8670da8306..69d0d376e28b 100644 --- a/arch/arc/kernel/entry.S +++ b/arch/arc/kernel/entry.S | |||
@@ -32,6 +32,9 @@ | |||
32 | * was being "CLEARED" rather then "SET". Since it is Loop INHIBIT Bit, | 32 | * was being "CLEARED" rather then "SET". Since it is Loop INHIBIT Bit, |
33 | * setting it and not clearing it clears ZOL context | 33 | * setting it and not clearing it clears ZOL context |
34 | * | 34 | * |
35 | * Vineetg: May 16th, 2008 | ||
36 | * - r25 now contains the Current Task when in kernel | ||
37 | * | ||
35 | * Vineetg: Dec 22, 2007 | 38 | * Vineetg: Dec 22, 2007 |
36 | * Minor Surgery of Low Level ISR to make it SMP safe | 39 | * Minor Surgery of Low Level ISR to make it SMP safe |
37 | * - MMU_SCRATCH0 Reg used for freeing up r9 in Level 1 ISR | 40 | * - MMU_SCRATCH0 Reg used for freeing up r9 in Level 1 ISR |
@@ -535,6 +538,17 @@ restore_regs : | |||
535 | ; XXX can this be optimised out | 538 | ; XXX can this be optimised out |
536 | IRQ_DISABLE_SAVE r9, r10 ;@r10 has prisitine (pre-disable) copy | 539 | IRQ_DISABLE_SAVE r9, r10 ;@r10 has prisitine (pre-disable) copy |
537 | 540 | ||
541 | #ifdef CONFIG_ARC_CURR_IN_REG | ||
542 | ; Restore User R25 | ||
543 | ; Earlier this used to be only for returning to user mode | ||
544 | ; However with 2 levels of IRQ this can also happen even if | ||
545 | ; in kernel mode | ||
546 | ld r9, [sp, PT_sp] | ||
547 | brhs r9, VMALLOC_START, 8f | ||
548 | RESTORE_USER_R25 | ||
549 | 8: | ||
550 | #endif | ||
551 | |||
538 | ; Restore REG File. In case multiple Events outstanding, | 552 | ; Restore REG File. In case multiple Events outstanding, |
539 | ; use the same priorty as rtie: EXCPN, L2 IRQ, L1 IRQ, None | 553 | ; use the same priorty as rtie: EXCPN, L2 IRQ, L1 IRQ, None |
540 | ; Note that we use realtime STATUS32 (not pt_regs->status32) to | 554 | ; Note that we use realtime STATUS32 (not pt_regs->status32) to |