Skip to content

Commit

Permalink
Redo RM9000 workaround which along with other DSP ASE changes was
Browse files Browse the repository at this point in the history
causing some headache for debuggers knowing about signal frames.

Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
  • Loading branch information
Ralf Baechle committed Oct 29, 2005
1 parent aac8aa7 commit 02416dc
Show file tree
Hide file tree
Showing 9 changed files with 98 additions and 86 deletions.
34 changes: 28 additions & 6 deletions arch/mips/kernel/signal-common.h
Original file line number Diff line number Diff line change
Expand Up @@ -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];
Expand All @@ -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;
}
59 changes: 27 additions & 32 deletions arch/mips/kernel/signal.c
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand All @@ -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"

Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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));
Expand Down Expand Up @@ -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);
Expand Down
16 changes: 16 additions & 0 deletions arch/mips/kernel/signal32.c
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand All @@ -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)

Expand Down Expand Up @@ -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)
Expand Down
32 changes: 13 additions & 19 deletions arch/mips/kernel/signal_n32.c
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand All @@ -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"

Expand All @@ -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);
Expand Down Expand Up @@ -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);
Expand Down
11 changes: 0 additions & 11 deletions include/asm-mips/cpu-features.h
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
6 changes: 0 additions & 6 deletions include/asm-mips/mach-ja/cpu-feature-overrides.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
6 changes: 0 additions & 6 deletions include/asm-mips/mach-ocelot3/cpu-feature-overrides.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
6 changes: 0 additions & 6 deletions include/asm-mips/mach-yosemite/cpu-feature-overrides.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
14 changes: 14 additions & 0 deletions include/asm-mips/war.h
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -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
Expand Down

0 comments on commit 02416dc

Please sign in to comment.