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

Redo RM9000 workaround which along with other DSP ASE changes was causing some headache for debuggers knowing about signal frames.

Signed-off-by: Ralf Baechle <ralf@linux-mips.org>

+98 -86
+28 -6
arch/mips/kernel/signal-common.h
··· 160 160 static inline void * 161 161 get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size) 162 162 { 163 - unsigned long sp, almask; 163 + unsigned long sp; 164 164 165 165 /* Default to using normal stack */ 166 166 sp = regs->regs[29]; ··· 176 176 if ((ka->sa.sa_flags & SA_ONSTACK) && (sas_ss_flags (sp) == 0)) 177 177 sp = current->sas_ss_sp + current->sas_ss_size; 178 178 179 - if (PLAT_TRAMPOLINE_STUFF_LINE) 180 - almask = ~(PLAT_TRAMPOLINE_STUFF_LINE - 1); 181 - else 182 - almask = ALMASK; 179 + return (void *)((sp - frame_size) & (ICACHE_REFILLS_WORKAROUND_WAR ? 32 : ALMASK)); 180 + } 183 181 184 - return (void *)((sp - frame_size) & almask); 182 + static inline int install_sigtramp(unsigned int __user *tramp, 183 + unsigned int syscall) 184 + { 185 + int err; 186 + 187 + /* 188 + * Set up the return code ... 189 + * 190 + * li v0, __NR__foo_sigreturn 191 + * syscall 192 + */ 193 + 194 + err = __put_user(0x24020000 + syscall, tramp + 0); 195 + err |= __put_user(0x0000000c , tramp + 1); 196 + if (ICACHE_REFILLS_WORKAROUND_WAR) { 197 + err |= __put_user(0, tramp + 2); 198 + err |= __put_user(0, tramp + 3); 199 + err |= __put_user(0, tramp + 4); 200 + err |= __put_user(0, tramp + 5); 201 + err |= __put_user(0, tramp + 6); 202 + err |= __put_user(0, tramp + 7); 203 + } 204 + flush_cache_sigtramp((unsigned long) tramp); 205 + 206 + return err; 185 207 }
+27 -32
arch/mips/kernel/signal.c
··· 8 8 * Copyright (C) 1999, 2000 Silicon Graphics, Inc. 9 9 */ 10 10 #include <linux/config.h> 11 + #include <linux/cache.h> 11 12 #include <linux/sched.h> 12 13 #include <linux/mm.h> 13 14 #include <linux/personality.h> ··· 31 30 #include <asm/uaccess.h> 32 31 #include <asm/ucontext.h> 33 32 #include <asm/cpu-features.h> 33 + #include <asm/war.h> 34 34 35 35 #include "signal-common.h" 36 36 ··· 159 157 return do_sigaltstack(uss, uoss, usp); 160 158 } 161 159 162 - #if PLAT_TRAMPOLINE_STUFF_LINE 163 - #define __tramp __attribute__((aligned(PLAT_TRAMPOLINE_STUFF_LINE))) 164 - #else 165 - #define __tramp 166 - #endif 167 - 160 + /* 161 + * Horribly complicated - with the bloody RM9000 workarounds enabled 162 + * the signal trampolines is moving to the end of the structure so we can 163 + * increase the alignment without breaking software compatibility. 164 + */ 168 165 #ifdef CONFIG_TRAD_SIGNALS 169 166 struct sigframe { 170 167 u32 sf_ass[4]; /* argument save space for o32 */ 171 - u32 sf_code[2] __tramp; /* signal trampoline */ 172 - struct sigcontext sf_sc __tramp; 168 + #if ICACHE_REFILLS_WORKAROUND_WAR 169 + u32 sf_pad[2]; 170 + #else 171 + u32 sf_code[2]; /* signal trampoline */ 172 + #endif 173 + struct sigcontext sf_sc; 173 174 sigset_t sf_mask; 175 + #if ICACHE_REFILLS_WORKAROUND_WAR 176 + u32 sf_code[8] ____cacheline_aligned; /* signal trampoline */ 177 + #endif 174 178 }; 175 179 #endif 176 180 177 181 struct rt_sigframe { 178 182 u32 rs_ass[4]; /* argument save space for o32 */ 179 - u32 rs_code[2] __tramp; /* signal trampoline */ 180 - struct siginfo rs_info __tramp; 183 + #if ICACHE_REFILLS_WORKAROUND_WAR 184 + u32 rs_pad[2]; 185 + #else 186 + u32 rs_code[2]; /* signal trampoline */ 187 + #endif 188 + struct siginfo rs_info; 181 189 struct ucontext rs_uc; 190 + #if ICACHE_REFILLS_WORKAROUND_WAR 191 + u32 rs_code[8] ____cacheline_aligned; /* signal trampoline */ 192 + #endif 182 193 }; 183 194 184 195 #ifdef CONFIG_TRAD_SIGNALS ··· 288 273 if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame))) 289 274 goto give_sigsegv; 290 275 291 - /* 292 - * Set up the return code ... 293 - * 294 - * li v0, __NR_sigreturn 295 - * syscall 296 - */ 297 - if (PLAT_TRAMPOLINE_STUFF_LINE) 298 - __clear_user(frame->sf_code, PLAT_TRAMPOLINE_STUFF_LINE); 299 - err |= __put_user(0x24020000 + __NR_sigreturn, frame->sf_code + 0); 300 - err |= __put_user(0x0000000c , frame->sf_code + 1); 301 - flush_cache_sigtramp((unsigned long) frame->sf_code); 276 + install_sigtramp(frame->sf_code, __NR_sigreturn); 302 277 303 278 err |= setup_sigcontext(regs, &frame->sf_sc); 304 279 err |= __copy_to_user(&frame->sf_mask, set, sizeof(*set)); ··· 334 329 if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame))) 335 330 goto give_sigsegv; 336 331 337 - /* 338 - * Set up the return code ... 339 - * 340 - * li v0, __NR_rt_sigreturn 341 - * syscall 342 - */ 343 - if (PLAT_TRAMPOLINE_STUFF_LINE) 344 - __clear_user(frame->rs_code, PLAT_TRAMPOLINE_STUFF_LINE); 345 - err |= __put_user(0x24020000 + __NR_rt_sigreturn, frame->rs_code + 0); 346 - err |= __put_user(0x0000000c , frame->rs_code + 1); 347 - flush_cache_sigtramp((unsigned long) frame->rs_code); 332 + install_sigtramp(frame->rs_code, __NR_rt_sigreturn); 348 333 349 334 /* Create siginfo. */ 350 335 err |= copy_siginfo_to_user(&frame->rs_info, info);
+16
arch/mips/kernel/signal32.c
··· 7 7 * Copyright (C) 1994 - 2000 Ralf Baechle 8 8 * Copyright (C) 1999, 2000 Silicon Graphics, Inc. 9 9 */ 10 + #include <linux/cache.h> 10 11 #include <linux/sched.h> 11 12 #include <linux/mm.h> 12 13 #include <linux/smp.h> ··· 31 30 #include <asm/ucontext.h> 32 31 #include <asm/system.h> 33 32 #include <asm/fpu.h> 33 + #include <asm/war.h> 34 34 35 35 #define SI_PAD_SIZE32 ((SI_MAX_SIZE/sizeof(int)) - 3) 36 36 ··· 394 392 395 393 struct sigframe { 396 394 u32 sf_ass[4]; /* argument save space for o32 */ 395 + #if ICACHE_REFILLS_WORKAROUND_WAR 396 + u32 sf_pad[2]; 397 + #else 397 398 u32 sf_code[2]; /* signal trampoline */ 399 + #endif 398 400 struct sigcontext32 sf_sc; 399 401 sigset_t sf_mask; 402 + #if ICACHE_REFILLS_WORKAROUND_WAR 403 + u32 sf_code[8] ____cacheline_aligned; /* signal trampoline */ 404 + #endif 400 405 }; 401 406 402 407 struct rt_sigframe32 { 403 408 u32 rs_ass[4]; /* argument save space for o32 */ 409 + #if ICACHE_REFILLS_WORKAROUND_WAR 410 + u32 rs_pad[2]; 411 + #else 404 412 u32 rs_code[2]; /* signal trampoline */ 413 + #endif 405 414 compat_siginfo_t rs_info; 406 415 struct ucontext32 rs_uc; 416 + #if ICACHE_REFILLS_WORKAROUND_WAR 417 + u32 rs_code[8] __attribute__((aligned(32))); /* signal trampoline */ 418 + #endif 407 419 }; 408 420 409 421 int copy_siginfo_to_user32(compat_siginfo_t *to, siginfo_t *from)
+13 -19
arch/mips/kernel/signal_n32.c
··· 15 15 * along with this program; if not, write to the Free Software 16 16 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 17 17 */ 18 + #include <linux/cache.h> 19 + #include <linux/sched.h> 18 20 #include <linux/sched.h> 19 21 #include <linux/mm.h> 20 22 #include <linux/smp.h> ··· 38 36 #include <asm/system.h> 39 37 #include <asm/fpu.h> 40 38 #include <asm/cpu-features.h> 39 + #include <asm/war.h> 41 40 42 41 #include "signal-common.h" 43 42 ··· 65 62 sigset_t uc_sigmask; /* mask last for extensibility */ 66 63 }; 67 64 68 - #if PLAT_TRAMPOLINE_STUFF_LINE 69 - #define __tramp __attribute__((aligned(PLAT_TRAMPOLINE_STUFF_LINE))) 70 - #else 71 - #define __tramp 72 - #endif 73 - 74 65 struct rt_sigframe_n32 { 75 66 u32 rs_ass[4]; /* argument save space for o32 */ 76 - u32 rs_code[2] __tramp; /* signal trampoline */ 77 - struct siginfo rs_info __tramp; 67 + #if ICACHE_REFILLS_WORKAROUND_WAR 68 + u32 rs_pad[2]; 69 + #else 70 + u32 rs_code[2]; /* signal trampoline */ 71 + #endif 72 + struct siginfo rs_info; 78 73 struct ucontextn32 rs_uc; 74 + #if ICACHE_REFILLS_WORKAROUND_WAR 75 + u32 rs_code[8] ____cacheline_aligned; /* signal trampoline */ 76 + #endif 79 77 }; 80 78 81 79 save_static_function(sysn32_rt_sigreturn); ··· 141 137 if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame))) 142 138 goto give_sigsegv; 143 139 144 - /* 145 - * Set up the return code ... 146 - * 147 - * li v0, __NR_rt_sigreturn 148 - * syscall 149 - */ 150 - if (PLAT_TRAMPOLINE_STUFF_LINE) 151 - __clear_user(frame->rs_code, PLAT_TRAMPOLINE_STUFF_LINE); 152 - err |= __put_user(0x24020000 + __NR_N32_rt_sigreturn, frame->rs_code + 0); 153 - err |= __put_user(0x0000000c , frame->rs_code + 1); 154 - flush_cache_sigtramp((unsigned long) frame->rs_code); 140 + install_sigtramp(frame->rs_code, __NR_N32_rt_sigreturn); 155 141 156 142 /* Create siginfo. */ 157 143 err |= copy_siginfo_to_user(&frame->rs_info, info);
-11
include/asm-mips/cpu-features.h
··· 109 109 #define cpu_has_dsp (cpu_data[0].ases & MIPS_ASE_DSP) 110 110 #endif 111 111 112 - /* 113 - * Certain CPUs may throw bizarre exceptions if not the whole cacheline 114 - * contains valid instructions. For these we ensure proper alignment of 115 - * signal trampolines and pad them to the size of a full cache lines with 116 - * nops. This is also used in structure definitions so can't be a test macro 117 - * like the others. 118 - */ 119 - #ifndef PLAT_TRAMPOLINE_STUFF_LINE 120 - #define PLAT_TRAMPOLINE_STUFF_LINE 0UL 121 - #endif 122 - 123 112 #ifdef CONFIG_32BIT 124 113 # ifndef cpu_has_nofpuex 125 114 # define cpu_has_nofpuex (cpu_data[0].options & MIPS_CPU_NOFPUEX)
-6
include/asm-mips/mach-ja/cpu-feature-overrides.h
··· 37 37 #define cpu_icache_line_size() 32 38 38 #define cpu_scache_line_size() 32 39 39 40 - /* 41 - * On the RM9000 we need to ensure that I-cache lines being fetches only 42 - * contain valid instructions are funny things will happen. 43 - */ 44 - #define PLAT_TRAMPOLINE_STUFF_LINE 32UL 45 - 46 40 #endif /* __ASM_MACH_JA_CPU_FEATURE_OVERRIDES_H */
-6
include/asm-mips/mach-ocelot3/cpu-feature-overrides.h
··· 40 40 #define cpu_icache_line_size() 32 41 41 #define cpu_scache_line_size() 32 42 42 43 - /* 44 - * On the RM9000 we need to ensure that I-cache lines being fetches only 45 - * contain valid instructions are funny things will happen. 46 - */ 47 - #define PLAT_TRAMPOLINE_STUFF_LINE 32UL 48 - 49 43 #endif /* __ASM_MACH_JA_CPU_FEATURE_OVERRIDES_H */
-6
include/asm-mips/mach-yosemite/cpu-feature-overrides.h
··· 37 37 #define cpu_icache_line_size() 32 38 38 #define cpu_scache_line_size() 32 39 39 40 - /* 41 - * On the RM9000 we need to ensure that I-cache lines being fetches only 42 - * contain valid instructions are funny things will happen. 43 - */ 44 - #define PLAT_TRAMPOLINE_STUFF_LINE 32UL 45 - 46 40 #endif /* __ASM_MACH_YOSEMITE_CPU_FEATURE_OVERRIDES_H */
+14
include/asm-mips/war.h
··· 177 177 #endif 178 178 179 179 /* 180 + * The RM9000 has a bug (though PMC-Sierra opposes it being called that) 181 + * where invalid instructions in the same I-cache line worth of instructions 182 + * being fetched may case spurious exceptions. 183 + */ 184 + #if defined(CONFIG_MOMENCO_JAGUAR_ATX) || defined(CONFIG_MOMENCO_OCELOT_3) || \ 185 + defined(CONFIG_PMC_YOSEMITE) 186 + #define ICACHE_REFILLS_WORKAROUND_WAR 1 187 + #endif 188 + 189 + 190 + /* 180 191 * ON the R10000 upto version 2.6 (not sure about 2.7) there is a bug that 181 192 * may cause ll / sc and lld / scd sequences to execute non-atomically. 182 193 */ ··· 198 187 /* 199 188 * Workarounds default to off 200 189 */ 190 + #ifndef ICACHE_REFILLS_WORKAROUND_WAR 191 + #define ICACHE_REFILLS_WORKAROUND_WAR 0 192 + #endif 201 193 #ifndef R4600_V1_INDEX_ICACHEOP_WAR 202 194 #define R4600_V1_INDEX_ICACHEOP_WAR 0 203 195 #endif