Skip to content
Snippets Groups Projects
Commit 02416dcf authored by Ralf Baechle's avatar Ralf Baechle
Browse files

Redo RM9000 workaround which along with other DSP ASE changes was

causing some headache for debuggers knowing about signal frames.

Signed-off-by: default avatarRalf Baechle <ralf@linux-mips.org>
parent aac8aa77
No related branches found
No related tags found
No related merge requests found
......@@ -160,7 +160,7 @@ restore_sigcontext(struct pt_regs *regs, struct sigcontext *sc)
static inline void *
get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size)
{
unsigned long sp, almask;
unsigned long sp;
/* Default to using normal stack */
sp = regs->regs[29];
......@@ -176,10 +176,32 @@ get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size)
if ((ka->sa.sa_flags & SA_ONSTACK) && (sas_ss_flags (sp) == 0))
sp = current->sas_ss_sp + current->sas_ss_size;
if (PLAT_TRAMPOLINE_STUFF_LINE)
almask = ~(PLAT_TRAMPOLINE_STUFF_LINE - 1);
else
almask = ALMASK;
return (void *)((sp - frame_size) & (ICACHE_REFILLS_WORKAROUND_WAR ? 32 : ALMASK));
}
static inline int install_sigtramp(unsigned int __user *tramp,
unsigned int syscall)
{
int err;
return (void *)((sp - frame_size) & almask);
/*
* Set up the return code ...
*
* li v0, __NR__foo_sigreturn
* syscall
*/
err = __put_user(0x24020000 + syscall, tramp + 0);
err |= __put_user(0x0000000c , tramp + 1);
if (ICACHE_REFILLS_WORKAROUND_WAR) {
err |= __put_user(0, tramp + 2);
err |= __put_user(0, tramp + 3);
err |= __put_user(0, tramp + 4);
err |= __put_user(0, tramp + 5);
err |= __put_user(0, tramp + 6);
err |= __put_user(0, tramp + 7);
}
flush_cache_sigtramp((unsigned long) tramp);
return err;
}
......@@ -8,6 +8,7 @@
* Copyright (C) 1999, 2000 Silicon Graphics, Inc.
*/
#include <linux/config.h>
#include <linux/cache.h>
#include <linux/sched.h>
#include <linux/mm.h>
#include <linux/personality.h>
......@@ -30,6 +31,7 @@
#include <asm/uaccess.h>
#include <asm/ucontext.h>
#include <asm/cpu-features.h>
#include <asm/war.h>
#include "signal-common.h"
......@@ -157,26 +159,39 @@ asmlinkage int sys_sigaltstack(nabi_no_regargs struct pt_regs regs)
return do_sigaltstack(uss, uoss, usp);
}
#if PLAT_TRAMPOLINE_STUFF_LINE
#define __tramp __attribute__((aligned(PLAT_TRAMPOLINE_STUFF_LINE)))
#else
#define __tramp
#endif
/*
* Horribly complicated - with the bloody RM9000 workarounds enabled
* the signal trampolines is moving to the end of the structure so we can
* increase the alignment without breaking software compatibility.
*/
#ifdef CONFIG_TRAD_SIGNALS
struct sigframe {
u32 sf_ass[4]; /* argument save space for o32 */
u32 sf_code[2] __tramp; /* signal trampoline */
struct sigcontext sf_sc __tramp;
#if ICACHE_REFILLS_WORKAROUND_WAR
u32 sf_pad[2];
#else
u32 sf_code[2]; /* signal trampoline */
#endif
struct sigcontext sf_sc;
sigset_t sf_mask;
#if ICACHE_REFILLS_WORKAROUND_WAR
u32 sf_code[8] ____cacheline_aligned; /* signal trampoline */
#endif
};
#endif
struct rt_sigframe {
u32 rs_ass[4]; /* argument save space for o32 */
u32 rs_code[2] __tramp; /* signal trampoline */
struct siginfo rs_info __tramp;
#if ICACHE_REFILLS_WORKAROUND_WAR
u32 rs_pad[2];
#else
u32 rs_code[2]; /* signal trampoline */
#endif
struct siginfo rs_info;
struct ucontext rs_uc;
#if ICACHE_REFILLS_WORKAROUND_WAR
u32 rs_code[8] ____cacheline_aligned; /* signal trampoline */
#endif
};
#ifdef CONFIG_TRAD_SIGNALS
......@@ -273,17 +288,7 @@ void setup_frame(struct k_sigaction * ka, struct pt_regs *regs,
if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame)))
goto give_sigsegv;
/*
* Set up the return code ...
*
* li v0, __NR_sigreturn
* syscall
*/
if (PLAT_TRAMPOLINE_STUFF_LINE)
__clear_user(frame->sf_code, PLAT_TRAMPOLINE_STUFF_LINE);
err |= __put_user(0x24020000 + __NR_sigreturn, frame->sf_code + 0);
err |= __put_user(0x0000000c , frame->sf_code + 1);
flush_cache_sigtramp((unsigned long) frame->sf_code);
install_sigtramp(frame->sf_code, __NR_sigreturn);
err |= setup_sigcontext(regs, &frame->sf_sc);
err |= __copy_to_user(&frame->sf_mask, set, sizeof(*set));
......@@ -329,17 +334,7 @@ void setup_rt_frame(struct k_sigaction * ka, struct pt_regs *regs,
if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame)))
goto give_sigsegv;
/*
* Set up the return code ...
*
* li v0, __NR_rt_sigreturn
* syscall
*/
if (PLAT_TRAMPOLINE_STUFF_LINE)
__clear_user(frame->rs_code, PLAT_TRAMPOLINE_STUFF_LINE);
err |= __put_user(0x24020000 + __NR_rt_sigreturn, frame->rs_code + 0);
err |= __put_user(0x0000000c , frame->rs_code + 1);
flush_cache_sigtramp((unsigned long) frame->rs_code);
install_sigtramp(frame->rs_code, __NR_rt_sigreturn);
/* Create siginfo. */
err |= copy_siginfo_to_user(&frame->rs_info, info);
......
......@@ -7,6 +7,7 @@
* Copyright (C) 1994 - 2000 Ralf Baechle
* Copyright (C) 1999, 2000 Silicon Graphics, Inc.
*/
#include <linux/cache.h>
#include <linux/sched.h>
#include <linux/mm.h>
#include <linux/smp.h>
......@@ -30,6 +31,7 @@
#include <asm/ucontext.h>
#include <asm/system.h>
#include <asm/fpu.h>
#include <asm/war.h>
#define SI_PAD_SIZE32 ((SI_MAX_SIZE/sizeof(int)) - 3)
......@@ -392,16 +394,30 @@ static int restore_sigcontext32(struct pt_regs *regs, struct sigcontext32 *sc)
struct sigframe {
u32 sf_ass[4]; /* argument save space for o32 */
#if ICACHE_REFILLS_WORKAROUND_WAR
u32 sf_pad[2];
#else
u32 sf_code[2]; /* signal trampoline */
#endif
struct sigcontext32 sf_sc;
sigset_t sf_mask;
#if ICACHE_REFILLS_WORKAROUND_WAR
u32 sf_code[8] ____cacheline_aligned; /* signal trampoline */
#endif
};
struct rt_sigframe32 {
u32 rs_ass[4]; /* argument save space for o32 */
#if ICACHE_REFILLS_WORKAROUND_WAR
u32 rs_pad[2];
#else
u32 rs_code[2]; /* signal trampoline */
#endif
compat_siginfo_t rs_info;
struct ucontext32 rs_uc;
#if ICACHE_REFILLS_WORKAROUND_WAR
u32 rs_code[8] __attribute__((aligned(32))); /* signal trampoline */
#endif
};
int copy_siginfo_to_user32(compat_siginfo_t *to, siginfo_t *from)
......
......@@ -15,6 +15,8 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include <linux/cache.h>
#include <linux/sched.h>
#include <linux/sched.h>
#include <linux/mm.h>
#include <linux/smp.h>
......@@ -36,6 +38,7 @@
#include <asm/system.h>
#include <asm/fpu.h>
#include <asm/cpu-features.h>
#include <asm/war.h>
#include "signal-common.h"
......@@ -62,17 +65,18 @@ struct ucontextn32 {
sigset_t uc_sigmask; /* mask last for extensibility */
};
#if PLAT_TRAMPOLINE_STUFF_LINE
#define __tramp __attribute__((aligned(PLAT_TRAMPOLINE_STUFF_LINE)))
#else
#define __tramp
#endif
struct rt_sigframe_n32 {
u32 rs_ass[4]; /* argument save space for o32 */
u32 rs_code[2] __tramp; /* signal trampoline */
struct siginfo rs_info __tramp;
#if ICACHE_REFILLS_WORKAROUND_WAR
u32 rs_pad[2];
#else
u32 rs_code[2]; /* signal trampoline */
#endif
struct siginfo rs_info;
struct ucontextn32 rs_uc;
#if ICACHE_REFILLS_WORKAROUND_WAR
u32 rs_code[8] ____cacheline_aligned; /* signal trampoline */
#endif
};
save_static_function(sysn32_rt_sigreturn);
......@@ -137,17 +141,7 @@ void setup_rt_frame_n32(struct k_sigaction * ka,
if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame)))
goto give_sigsegv;
/*
* Set up the return code ...
*
* li v0, __NR_rt_sigreturn
* syscall
*/
if (PLAT_TRAMPOLINE_STUFF_LINE)
__clear_user(frame->rs_code, PLAT_TRAMPOLINE_STUFF_LINE);
err |= __put_user(0x24020000 + __NR_N32_rt_sigreturn, frame->rs_code + 0);
err |= __put_user(0x0000000c , frame->rs_code + 1);
flush_cache_sigtramp((unsigned long) frame->rs_code);
install_sigtramp(frame->rs_code, __NR_N32_rt_sigreturn);
/* Create siginfo. */
err |= copy_siginfo_to_user(&frame->rs_info, info);
......
......@@ -109,17 +109,6 @@
#define cpu_has_dsp (cpu_data[0].ases & MIPS_ASE_DSP)
#endif
/*
* Certain CPUs may throw bizarre exceptions if not the whole cacheline
* contains valid instructions. For these we ensure proper alignment of
* signal trampolines and pad them to the size of a full cache lines with
* nops. This is also used in structure definitions so can't be a test macro
* like the others.
*/
#ifndef PLAT_TRAMPOLINE_STUFF_LINE
#define PLAT_TRAMPOLINE_STUFF_LINE 0UL
#endif
#ifdef CONFIG_32BIT
# ifndef cpu_has_nofpuex
# define cpu_has_nofpuex (cpu_data[0].options & MIPS_CPU_NOFPUEX)
......
......@@ -37,10 +37,4 @@
#define cpu_icache_line_size() 32
#define cpu_scache_line_size() 32
/*
* On the RM9000 we need to ensure that I-cache lines being fetches only
* contain valid instructions are funny things will happen.
*/
#define PLAT_TRAMPOLINE_STUFF_LINE 32UL
#endif /* __ASM_MACH_JA_CPU_FEATURE_OVERRIDES_H */
......@@ -40,10 +40,4 @@
#define cpu_icache_line_size() 32
#define cpu_scache_line_size() 32
/*
* On the RM9000 we need to ensure that I-cache lines being fetches only
* contain valid instructions are funny things will happen.
*/
#define PLAT_TRAMPOLINE_STUFF_LINE 32UL
#endif /* __ASM_MACH_JA_CPU_FEATURE_OVERRIDES_H */
......@@ -37,10 +37,4 @@
#define cpu_icache_line_size() 32
#define cpu_scache_line_size() 32
/*
* On the RM9000 we need to ensure that I-cache lines being fetches only
* contain valid instructions are funny things will happen.
*/
#define PLAT_TRAMPOLINE_STUFF_LINE 32UL
#endif /* __ASM_MACH_YOSEMITE_CPU_FEATURE_OVERRIDES_H */
......@@ -176,6 +176,17 @@
#define RM9000_CDEX_SMP_WAR 1
#endif
/*
* The RM9000 has a bug (though PMC-Sierra opposes it being called that)
* where invalid instructions in the same I-cache line worth of instructions
* being fetched may case spurious exceptions.
*/
#if defined(CONFIG_MOMENCO_JAGUAR_ATX) || defined(CONFIG_MOMENCO_OCELOT_3) || \
defined(CONFIG_PMC_YOSEMITE)
#define ICACHE_REFILLS_WORKAROUND_WAR 1
#endif
/*
* ON the R10000 upto version 2.6 (not sure about 2.7) there is a bug that
* may cause ll / sc and lld / scd sequences to execute non-atomically.
......@@ -187,6 +198,9 @@
/*
* Workarounds default to off
*/
#ifndef ICACHE_REFILLS_WORKAROUND_WAR
#define ICACHE_REFILLS_WORKAROUND_WAR 0
#endif
#ifndef R4600_V1_INDEX_ICACHEOP_WAR
#define R4600_V1_INDEX_ICACHEOP_WAR 0
#endif
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment