diff options
Diffstat (limited to 'arch')
-rw-r--r-- | arch/mips/Kconfig | 11 | ||||
-rw-r--r-- | arch/mips/kernel/cpu-probe.c | 26 | ||||
-rw-r--r-- | arch/mips/kernel/process.c | 14 |
3 files changed, 50 insertions, 1 deletions
diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index 5c863bcd561..1e3aeccd732 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -1190,8 +1190,19 @@ config SYS_HAS_CPU_RM9000 config SYS_HAS_CPU_SB1 bool +# +# CPU may reorder R->R, R->W, W->R, W->W +# Reordering beyond LL and SC is handled in WEAK_REORDERING_BEYOND_LLSC +# config WEAK_ORDERING bool + +# +# CPU may reorder reads and writes beyond LL/SC +# CPU may reorder R->LL, R->LL, W->LL, W->LL, R->SC, R->SC, W->SC, W->SC +# +config WEAK_REORDERING_BEYOND_LLSC + bool endmenu # diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c index c6b8b074a81..06448a9656d 100644 --- a/arch/mips/kernel/cpu-probe.c +++ b/arch/mips/kernel/cpu-probe.c @@ -75,6 +75,27 @@ static void r4k_wait_irqoff(void) local_irq_enable(); } +/* + * The RM7000 variant has to handle erratum 38. The workaround is to not + * have any pending stores when the WAIT instruction is executed. + */ +static void rm7k_wait_irqoff(void) +{ + local_irq_disable(); + if (!need_resched()) + __asm__( + " .set push \n" + " .set mips3 \n" + " .set noat \n" + " mfc0 $1, $12 \n" + " sync \n" + " mtc0 $1, $12 # stalls until W stage \n" + " wait \n" + " mtc0 $1, $12 # stalls until W stage \n" + " .set pop \n"); + local_irq_enable(); +} + /* The Au1xxx wait is available only if using 32khz counter or * external timer source, but specifically not CP0 Counter. */ int allow_au1k_wait; @@ -132,7 +153,6 @@ static inline void check_wait(void) case CPU_R4700: case CPU_R5000: case CPU_NEVADA: - case CPU_RM7000: case CPU_4KC: case CPU_4KEC: case CPU_4KSC: @@ -142,6 +162,10 @@ static inline void check_wait(void) cpu_wait = r4k_wait; break; + case CPU_RM7000: + cpu_wait = rm7k_wait_irqoff; + break; + case CPU_24K: case CPU_34K: cpu_wait = r4k_wait; diff --git a/arch/mips/kernel/process.c b/arch/mips/kernel/process.c index 8f4cf27c715..bd05f5a927e 100644 --- a/arch/mips/kernel/process.c +++ b/arch/mips/kernel/process.c @@ -25,7 +25,9 @@ #include <linux/init.h> #include <linux/completion.h> #include <linux/kallsyms.h> +#include <linux/random.h> +#include <asm/asm.h> #include <asm/bootinfo.h> #include <asm/cpu.h> #include <asm/dsp.h> @@ -460,3 +462,15 @@ unsigned long get_wchan(struct task_struct *task) out: return pc; } + +/* + * Don't forget that the stack pointer must be aligned on a 8 bytes + * boundary for 32-bits ABI and 16 bytes for 64-bits ABI. + */ +unsigned long arch_align_stack(unsigned long sp) +{ + if (!(current->personality & ADDR_NO_RANDOMIZE) && randomize_va_space) + sp -= get_random_int() & ~PAGE_MASK; + + return sp & ALMASK; +} |