Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

MIPS: Make SAVE_SOME more standard

Modify the SAVE_SOME macro to look more like a standard
function, doing the arithmetic for the frame on the SP
register instead of copying it from K1, and by saving
the stored EPC from the RA. This lets the get_frame_info()
function process this function like any other. It also
remove an instruction or two from the kernel entry,
making it more efficient.

unwind_stack_by_address() has special handling for
the top of the interrupt stack, but without this change
unwinding will still fail if you get an interrupt while
handling an interrupt and try to do a traceback from
the second interrupt.

This change modifies the get_saved_sp macro to
optionally store the fetched value right into sp and store the
old SP value into K0. Then it's just a matter of subtracting
the frame from SP and storing the old SP from K0.

This required changing the DADDI workaround a bit, since K0
holds the SP, we had to use K1 for AT. But it eliminated
some of the special handling for the DADDI workaround.

Saving the RA register was moved up to before fetching the
CP0_EPC register, so the CP0_EPC register could be stored
into RA and the saved. This lets the traceback code know
where RA is actually stored.

Signed-off-by: Corey Minyard <cminyard@mvista.com>
Cc: linux-mips@linux-mips.org
Cc: linux-kernel@vger.kernel.org
Patchwork: https://patchwork.linux-mips.org/patch/16991/
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>

authored by

Corey Minyard and committed by
Ralf Baechle
9fef6868 aee16625

+37 -14
+37 -14
arch/mips/include/asm/stackframe.h
··· 83 83 LONG_S $30, PT_R30(sp) 84 84 .endm 85 85 86 + /* 87 + * get_saved_sp returns the SP for the current CPU by looking in the 88 + * kernelsp array for it. If tosp is set, it stores the current sp in 89 + * k0 and loads the new value in sp. If not, it clobbers k0 and 90 + * stores the new value in k1, leaving sp unaffected. 91 + */ 86 92 #ifdef CONFIG_SMP 87 - .macro get_saved_sp /* SMP variation */ 93 + 94 + /* SMP variation */ 95 + .macro get_saved_sp docfi=0 tosp=0 88 96 ASM_CPUID_MFC0 k0, ASM_SMP_CPUID_REG 89 97 #if defined(CONFIG_32BIT) || defined(KBUILD_64BIT_SYM32) 90 98 lui k1, %hi(kernelsp) ··· 105 97 #endif 106 98 LONG_SRL k0, SMP_CPUID_PTRSHIFT 107 99 LONG_ADDU k1, k0 100 + .if \tosp 101 + move k0, sp 102 + .if \docfi 103 + .cfi_register sp, k0 104 + .endif 105 + LONG_L sp, %lo(kernelsp)(k1) 106 + .else 108 107 LONG_L k1, %lo(kernelsp)(k1) 108 + .endif 109 109 .endm 110 110 111 111 .macro set_saved_sp stackp temp temp2 ··· 122 106 LONG_S \stackp, kernelsp(\temp) 123 107 .endm 124 108 #else /* !CONFIG_SMP */ 125 - .macro get_saved_sp /* Uniprocessor variation */ 109 + /* Uniprocessor variation */ 110 + .macro get_saved_sp docfi=0 tosp=0 126 111 #ifdef CONFIG_CPU_JUMP_WORKAROUNDS 127 112 /* 128 113 * Clear BTB (branch target buffer), forbid RAS (return address ··· 152 135 daddiu k1, %hi(kernelsp) 153 136 dsll k1, k1, 16 154 137 #endif 138 + .if \tosp 139 + move k0, sp 140 + .if \docfi 141 + .cfi_register sp, k0 142 + .endif 143 + LONG_L sp, %lo(kernelsp)(k1) 144 + .else 155 145 LONG_L k1, %lo(kernelsp)(k1) 146 + .endif 156 147 .endm 157 148 158 149 .macro set_saved_sp stackp temp temp2 ··· 176 151 sll k0, 3 /* extract cu0 bit */ 177 152 .set noreorder 178 153 bltz k0, 8f 179 - move k1, sp 180 154 #ifdef CONFIG_EVA 181 155 /* 182 156 * Flush interAptiv's Return Prediction Stack (RPS) by writing ··· 202 178 MTC0 k0, CP0_ENTRYHI 203 179 #endif 204 180 .set reorder 181 + move k0, sp 205 182 /* Called from user mode, new stack. */ 206 183 get_saved_sp 207 - #ifndef CONFIG_CPU_DADDI_WORKAROUNDS 208 - 8: move k0, sp 209 - PTR_SUBU sp, k1, PT_SIZE 210 - #else 211 - .set at=k0 212 - 8: PTR_SUBU k1, PT_SIZE 184 + 8: 185 + #ifdef CONFIG_CPU_DADDI_WORKAROUNDS 186 + .set at=k1 187 + #endif 188 + PTR_SUBU sp, PT_SIZE 189 + #ifdef CONFIG_CPU_DADDI_WORKAROUNDS 213 190 .set noat 214 - move k0, sp 215 - move sp, k1 216 191 #endif 217 192 LONG_S k0, PT_R29(sp) 218 193 LONG_S $3, PT_R3(sp) ··· 229 206 LONG_S $5, PT_R5(sp) 230 207 LONG_S v1, PT_CAUSE(sp) 231 208 LONG_S $6, PT_R6(sp) 232 - MFC0 v1, CP0_EPC 209 + LONG_S ra, PT_R31(sp) 210 + MFC0 ra, CP0_EPC 233 211 LONG_S $7, PT_R7(sp) 234 212 #ifdef CONFIG_64BIT 235 213 LONG_S $8, PT_R8(sp) 236 214 LONG_S $9, PT_R9(sp) 237 215 #endif 238 - LONG_S v1, PT_EPC(sp) 216 + LONG_S ra, PT_EPC(sp) 239 217 LONG_S $25, PT_R25(sp) 240 218 LONG_S $28, PT_R28(sp) 241 - LONG_S $31, PT_R31(sp) 242 219 243 220 /* Set thread_info if we're coming from user mode */ 244 221 mfc0 k0, CP0_STATUS