mirror of
https://github.com/torvalds/linux.git
synced 2024-12-28 05:41:55 +00:00
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>
This commit is contained in:
parent
aac8aa7717
commit
02416dcf5a
@ -160,7 +160,7 @@ restore_sigcontext(struct pt_regs *regs, struct sigcontext *sc)
|
|||||||
static inline void *
|
static inline void *
|
||||||
get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size)
|
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 */
|
/* Default to using normal stack */
|
||||||
sp = regs->regs[29];
|
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))
|
if ((ka->sa.sa_flags & SA_ONSTACK) && (sas_ss_flags (sp) == 0))
|
||||||
sp = current->sas_ss_sp + current->sas_ss_size;
|
sp = current->sas_ss_sp + current->sas_ss_size;
|
||||||
|
|
||||||
if (PLAT_TRAMPOLINE_STUFF_LINE)
|
return (void *)((sp - frame_size) & (ICACHE_REFILLS_WORKAROUND_WAR ? 32 : ALMASK));
|
||||||
almask = ~(PLAT_TRAMPOLINE_STUFF_LINE - 1);
|
}
|
||||||
else
|
|
||||||
almask = ALMASK;
|
static inline int install_sigtramp(unsigned int __user *tramp,
|
||||||
|
unsigned int syscall)
|
||||||
return (void *)((sp - frame_size) & almask);
|
{
|
||||||
|
int err;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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.
|
* Copyright (C) 1999, 2000 Silicon Graphics, Inc.
|
||||||
*/
|
*/
|
||||||
#include <linux/config.h>
|
#include <linux/config.h>
|
||||||
|
#include <linux/cache.h>
|
||||||
#include <linux/sched.h>
|
#include <linux/sched.h>
|
||||||
#include <linux/mm.h>
|
#include <linux/mm.h>
|
||||||
#include <linux/personality.h>
|
#include <linux/personality.h>
|
||||||
@ -30,6 +31,7 @@
|
|||||||
#include <asm/uaccess.h>
|
#include <asm/uaccess.h>
|
||||||
#include <asm/ucontext.h>
|
#include <asm/ucontext.h>
|
||||||
#include <asm/cpu-features.h>
|
#include <asm/cpu-features.h>
|
||||||
|
#include <asm/war.h>
|
||||||
|
|
||||||
#include "signal-common.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);
|
return do_sigaltstack(uss, uoss, usp);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if PLAT_TRAMPOLINE_STUFF_LINE
|
/*
|
||||||
#define __tramp __attribute__((aligned(PLAT_TRAMPOLINE_STUFF_LINE)))
|
* Horribly complicated - with the bloody RM9000 workarounds enabled
|
||||||
#else
|
* the signal trampolines is moving to the end of the structure so we can
|
||||||
#define __tramp
|
* increase the alignment without breaking software compatibility.
|
||||||
#endif
|
*/
|
||||||
|
|
||||||
#ifdef CONFIG_TRAD_SIGNALS
|
#ifdef CONFIG_TRAD_SIGNALS
|
||||||
struct sigframe {
|
struct sigframe {
|
||||||
u32 sf_ass[4]; /* argument save space for o32 */
|
u32 sf_ass[4]; /* argument save space for o32 */
|
||||||
u32 sf_code[2] __tramp; /* signal trampoline */
|
#if ICACHE_REFILLS_WORKAROUND_WAR
|
||||||
struct sigcontext sf_sc __tramp;
|
u32 sf_pad[2];
|
||||||
|
#else
|
||||||
|
u32 sf_code[2]; /* signal trampoline */
|
||||||
|
#endif
|
||||||
|
struct sigcontext sf_sc;
|
||||||
sigset_t sf_mask;
|
sigset_t sf_mask;
|
||||||
|
#if ICACHE_REFILLS_WORKAROUND_WAR
|
||||||
|
u32 sf_code[8] ____cacheline_aligned; /* signal trampoline */
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
struct rt_sigframe {
|
struct rt_sigframe {
|
||||||
u32 rs_ass[4]; /* argument save space for o32 */
|
u32 rs_ass[4]; /* argument save space for o32 */
|
||||||
u32 rs_code[2] __tramp; /* signal trampoline */
|
#if ICACHE_REFILLS_WORKAROUND_WAR
|
||||||
struct siginfo rs_info __tramp;
|
u32 rs_pad[2];
|
||||||
|
#else
|
||||||
|
u32 rs_code[2]; /* signal trampoline */
|
||||||
|
#endif
|
||||||
|
struct siginfo rs_info;
|
||||||
struct ucontext rs_uc;
|
struct ucontext rs_uc;
|
||||||
|
#if ICACHE_REFILLS_WORKAROUND_WAR
|
||||||
|
u32 rs_code[8] ____cacheline_aligned; /* signal trampoline */
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef CONFIG_TRAD_SIGNALS
|
#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)))
|
if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame)))
|
||||||
goto give_sigsegv;
|
goto give_sigsegv;
|
||||||
|
|
||||||
/*
|
install_sigtramp(frame->sf_code, __NR_sigreturn);
|
||||||
* 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);
|
|
||||||
|
|
||||||
err |= setup_sigcontext(regs, &frame->sf_sc);
|
err |= setup_sigcontext(regs, &frame->sf_sc);
|
||||||
err |= __copy_to_user(&frame->sf_mask, set, sizeof(*set));
|
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)))
|
if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame)))
|
||||||
goto give_sigsegv;
|
goto give_sigsegv;
|
||||||
|
|
||||||
/*
|
install_sigtramp(frame->rs_code, __NR_rt_sigreturn);
|
||||||
* 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);
|
|
||||||
|
|
||||||
/* Create siginfo. */
|
/* Create siginfo. */
|
||||||
err |= copy_siginfo_to_user(&frame->rs_info, info);
|
err |= copy_siginfo_to_user(&frame->rs_info, info);
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
* Copyright (C) 1994 - 2000 Ralf Baechle
|
* Copyright (C) 1994 - 2000 Ralf Baechle
|
||||||
* Copyright (C) 1999, 2000 Silicon Graphics, Inc.
|
* Copyright (C) 1999, 2000 Silicon Graphics, Inc.
|
||||||
*/
|
*/
|
||||||
|
#include <linux/cache.h>
|
||||||
#include <linux/sched.h>
|
#include <linux/sched.h>
|
||||||
#include <linux/mm.h>
|
#include <linux/mm.h>
|
||||||
#include <linux/smp.h>
|
#include <linux/smp.h>
|
||||||
@ -30,6 +31,7 @@
|
|||||||
#include <asm/ucontext.h>
|
#include <asm/ucontext.h>
|
||||||
#include <asm/system.h>
|
#include <asm/system.h>
|
||||||
#include <asm/fpu.h>
|
#include <asm/fpu.h>
|
||||||
|
#include <asm/war.h>
|
||||||
|
|
||||||
#define SI_PAD_SIZE32 ((SI_MAX_SIZE/sizeof(int)) - 3)
|
#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 {
|
struct sigframe {
|
||||||
u32 sf_ass[4]; /* argument save space for o32 */
|
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 */
|
u32 sf_code[2]; /* signal trampoline */
|
||||||
|
#endif
|
||||||
struct sigcontext32 sf_sc;
|
struct sigcontext32 sf_sc;
|
||||||
sigset_t sf_mask;
|
sigset_t sf_mask;
|
||||||
|
#if ICACHE_REFILLS_WORKAROUND_WAR
|
||||||
|
u32 sf_code[8] ____cacheline_aligned; /* signal trampoline */
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
struct rt_sigframe32 {
|
struct rt_sigframe32 {
|
||||||
u32 rs_ass[4]; /* argument save space for o32 */
|
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 */
|
u32 rs_code[2]; /* signal trampoline */
|
||||||
|
#endif
|
||||||
compat_siginfo_t rs_info;
|
compat_siginfo_t rs_info;
|
||||||
struct ucontext32 rs_uc;
|
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)
|
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
|
* along with this program; if not, write to the Free Software
|
||||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
* 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/sched.h>
|
||||||
#include <linux/mm.h>
|
#include <linux/mm.h>
|
||||||
#include <linux/smp.h>
|
#include <linux/smp.h>
|
||||||
@ -36,6 +38,7 @@
|
|||||||
#include <asm/system.h>
|
#include <asm/system.h>
|
||||||
#include <asm/fpu.h>
|
#include <asm/fpu.h>
|
||||||
#include <asm/cpu-features.h>
|
#include <asm/cpu-features.h>
|
||||||
|
#include <asm/war.h>
|
||||||
|
|
||||||
#include "signal-common.h"
|
#include "signal-common.h"
|
||||||
|
|
||||||
@ -62,17 +65,18 @@ struct ucontextn32 {
|
|||||||
sigset_t uc_sigmask; /* mask last for extensibility */
|
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 {
|
struct rt_sigframe_n32 {
|
||||||
u32 rs_ass[4]; /* argument save space for o32 */
|
u32 rs_ass[4]; /* argument save space for o32 */
|
||||||
u32 rs_code[2] __tramp; /* signal trampoline */
|
#if ICACHE_REFILLS_WORKAROUND_WAR
|
||||||
struct siginfo rs_info __tramp;
|
u32 rs_pad[2];
|
||||||
|
#else
|
||||||
|
u32 rs_code[2]; /* signal trampoline */
|
||||||
|
#endif
|
||||||
|
struct siginfo rs_info;
|
||||||
struct ucontextn32 rs_uc;
|
struct ucontextn32 rs_uc;
|
||||||
|
#if ICACHE_REFILLS_WORKAROUND_WAR
|
||||||
|
u32 rs_code[8] ____cacheline_aligned; /* signal trampoline */
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
save_static_function(sysn32_rt_sigreturn);
|
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)))
|
if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame)))
|
||||||
goto give_sigsegv;
|
goto give_sigsegv;
|
||||||
|
|
||||||
/*
|
install_sigtramp(frame->rs_code, __NR_N32_rt_sigreturn);
|
||||||
* 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);
|
|
||||||
|
|
||||||
/* Create siginfo. */
|
/* Create siginfo. */
|
||||||
err |= copy_siginfo_to_user(&frame->rs_info, info);
|
err |= copy_siginfo_to_user(&frame->rs_info, info);
|
||||||
|
@ -109,17 +109,6 @@
|
|||||||
#define cpu_has_dsp (cpu_data[0].ases & MIPS_ASE_DSP)
|
#define cpu_has_dsp (cpu_data[0].ases & MIPS_ASE_DSP)
|
||||||
#endif
|
#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
|
#ifdef CONFIG_32BIT
|
||||||
# ifndef cpu_has_nofpuex
|
# ifndef cpu_has_nofpuex
|
||||||
# define cpu_has_nofpuex (cpu_data[0].options & MIPS_CPU_NOFPUEX)
|
# define cpu_has_nofpuex (cpu_data[0].options & MIPS_CPU_NOFPUEX)
|
||||||
|
@ -37,10 +37,4 @@
|
|||||||
#define cpu_icache_line_size() 32
|
#define cpu_icache_line_size() 32
|
||||||
#define cpu_scache_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 */
|
#endif /* __ASM_MACH_JA_CPU_FEATURE_OVERRIDES_H */
|
||||||
|
@ -40,10 +40,4 @@
|
|||||||
#define cpu_icache_line_size() 32
|
#define cpu_icache_line_size() 32
|
||||||
#define cpu_scache_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 */
|
#endif /* __ASM_MACH_JA_CPU_FEATURE_OVERRIDES_H */
|
||||||
|
@ -37,10 +37,4 @@
|
|||||||
#define cpu_icache_line_size() 32
|
#define cpu_icache_line_size() 32
|
||||||
#define cpu_scache_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 */
|
#endif /* __ASM_MACH_YOSEMITE_CPU_FEATURE_OVERRIDES_H */
|
||||||
|
@ -176,6 +176,17 @@
|
|||||||
#define RM9000_CDEX_SMP_WAR 1
|
#define RM9000_CDEX_SMP_WAR 1
|
||||||
#endif
|
#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
|
* 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.
|
* may cause ll / sc and lld / scd sequences to execute non-atomically.
|
||||||
@ -187,6 +198,9 @@
|
|||||||
/*
|
/*
|
||||||
* Workarounds default to off
|
* Workarounds default to off
|
||||||
*/
|
*/
|
||||||
|
#ifndef ICACHE_REFILLS_WORKAROUND_WAR
|
||||||
|
#define ICACHE_REFILLS_WORKAROUND_WAR 0
|
||||||
|
#endif
|
||||||
#ifndef R4600_V1_INDEX_ICACHEOP_WAR
|
#ifndef R4600_V1_INDEX_ICACHEOP_WAR
|
||||||
#define R4600_V1_INDEX_ICACHEOP_WAR 0
|
#define R4600_V1_INDEX_ICACHEOP_WAR 0
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
Reference in New Issue
Block a user