MIPS: Octeon: Apply CN63XXP1 errata workarounds.

The CN63XXP1 needs a couple of workarounds to ensure memory is not written
in unexpected ways.

All PREF with hints in the range 0-4,6-24 are replaced with PREF 28.  We
pass a flag to the assembler to cover compiler generated code, and patch
uasm for the dynamically generated code.

The write buffer threshold is reduced to 4.

Signed-off-by: David Daney <ddaney@caviumnetworks.com>
Patchwork: http://patchwork.linux-mips.org/patch/1672/
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
This commit is contained in:
David Daney 2010-10-07 16:03:53 -07:00 committed by Ralf Baechle
parent 468ffde46d
commit c9941158fd
4 changed files with 69 additions and 5 deletions

View File

@ -156,6 +156,7 @@ cflags-$(CONFIG_CPU_CAVIUM_OCTEON) += $(call cc-option,-march=octeon) -Wa,--trap
ifeq (,$(findstring march=octeon, $(cflags-$(CONFIG_CPU_CAVIUM_OCTEON)))) ifeq (,$(findstring march=octeon, $(cflags-$(CONFIG_CPU_CAVIUM_OCTEON))))
cflags-$(CONFIG_CPU_CAVIUM_OCTEON) += -Wa,-march=octeon cflags-$(CONFIG_CPU_CAVIUM_OCTEON) += -Wa,-march=octeon
endif endif
cflags-$(CONFIG_CAVIUM_CN63XXP1) += -Wa,-mfix-cn63xxp1
cflags-$(CONFIG_CPU_R4000_WORKAROUNDS) += $(call cc-option,-mfix-r4000,) cflags-$(CONFIG_CPU_R4000_WORKAROUNDS) += $(call cc-option,-mfix-r4000,)
cflags-$(CONFIG_CPU_R4400_WORKAROUNDS) += $(call cc-option,-mfix-r4400,) cflags-$(CONFIG_CPU_R4400_WORKAROUNDS) += $(call cc-option,-mfix-r4400,)

View File

@ -3,6 +3,17 @@ config CAVIUM_OCTEON_SPECIFIC_OPTIONS
depends on CPU_CAVIUM_OCTEON depends on CPU_CAVIUM_OCTEON
default "y" default "y"
config CAVIUM_CN63XXP1
bool "Enable CN63XXP1 errata worarounds"
depends on CAVIUM_OCTEON_SPECIFIC_OPTIONS
default "n"
help
The CN63XXP1 chip requires build time workarounds to
function reliably, select this option to enable them. These
workarounds will cause a slight decrease in performance on
non-CN63XXP1 hardware, so it is recommended to select "n"
unless it is known the workarounds are needed.
config CAVIUM_OCTEON_2ND_KERNEL config CAVIUM_OCTEON_2ND_KERNEL
bool "Build the kernel to be used as a 2nd kernel on the same chip" bool "Build the kernel to be used as a 2nd kernel on the same chip"
depends on CAVIUM_OCTEON_SPECIFIC_OPTIONS depends on CAVIUM_OCTEON_SPECIFIC_OPTIONS

View File

@ -356,8 +356,18 @@ void octeon_user_io_init(void)
cvmmemctl.s.wbfltime = 0; cvmmemctl.s.wbfltime = 0;
/* R/W If set, do not put Istream in the L2 cache. */ /* R/W If set, do not put Istream in the L2 cache. */
cvmmemctl.s.istrnol2 = 0; cvmmemctl.s.istrnol2 = 0;
/* R/W The write buffer threshold. */
cvmmemctl.s.wbthresh = 10; /*
* R/W The write buffer threshold. As per erratum Core-14752
* for CN63XX, a sc/scd might fail if the write buffer is
* full. Lowering WBTHRESH greatly lowers the chances of the
* write buffer ever being full and triggering the erratum.
*/
if (OCTEON_IS_MODEL(OCTEON_CN63XX_PASS1_X))
cvmmemctl.s.wbthresh = 4;
else
cvmmemctl.s.wbthresh = 10;
/* R/W If set, CVMSEG is available for loads/stores in /* R/W If set, CVMSEG is available for loads/stores in
* kernel/debug mode. */ * kernel/debug mode. */
#if CONFIG_CAVIUM_OCTEON_CVMSEG_SIZE > 0 #if CONFIG_CAVIUM_OCTEON_CVMSEG_SIZE > 0
@ -375,14 +385,13 @@ void octeon_user_io_init(void)
* is max legal value. */ * is max legal value. */
cvmmemctl.s.lmemsz = CONFIG_CAVIUM_OCTEON_CVMSEG_SIZE; cvmmemctl.s.lmemsz = CONFIG_CAVIUM_OCTEON_CVMSEG_SIZE;
write_c0_cvmmemctl(cvmmemctl.u64);
if (smp_processor_id() == 0) if (smp_processor_id() == 0)
pr_notice("CVMSEG size: %d cache lines (%d bytes)\n", pr_notice("CVMSEG size: %d cache lines (%d bytes)\n",
CONFIG_CAVIUM_OCTEON_CVMSEG_SIZE, CONFIG_CAVIUM_OCTEON_CVMSEG_SIZE,
CONFIG_CAVIUM_OCTEON_CVMSEG_SIZE * 128); CONFIG_CAVIUM_OCTEON_CVMSEG_SIZE * 128);
write_c0_cvmmemctl(cvmmemctl.u64);
/* Move the performance counter interrupts to IRQ 6 */ /* Move the performance counter interrupts to IRQ 6 */
cvmctl = read_c0_cvmctl(); cvmctl = read_c0_cvmctl();
cvmctl &= ~(7 << 7); cvmctl &= ~(7 << 7);
@ -758,6 +767,31 @@ EXPORT_SYMBOL(prom_putchar);
void prom_free_prom_memory(void) void prom_free_prom_memory(void)
{ {
if (OCTEON_IS_MODEL(OCTEON_CN63XX_PASS1_X)) {
/* Check for presence of Core-14449 fix. */
u32 insn;
u32 *foo;
foo = &insn;
asm volatile("# before" : : : "memory");
prefetch(foo);
asm volatile(
".set push\n\t"
".set noreorder\n\t"
"bal 1f\n\t"
"nop\n"
"1:\tlw %0,-12($31)\n\t"
".set pop\n\t"
: "=r" (insn) : : "$31", "memory");
if ((insn >> 26) != 0x33)
panic("No PREF instruction at Core-14449 probe point.\n");
if (((insn >> 16) & 0x1f) != 28)
panic("Core-14449 WAR not in place (%04x).\n"
"Please build kernel with proper options (CONFIG_CAVIUM_CN63XXP1).\n", insn);
}
#ifdef CONFIG_CAVIUM_DECODE_RSL #ifdef CONFIG_CAVIUM_DECODE_RSL
cvmx_interrupt_rsl_enable(); cvmx_interrupt_rsl_enable();

View File

@ -405,7 +405,6 @@ I_u1u2u3(_mfc0)
I_u1u2u3(_mtc0) I_u1u2u3(_mtc0)
I_u2u1u3(_ori) I_u2u1u3(_ori)
I_u3u1u2(_or) I_u3u1u2(_or)
I_u2s3u1(_pref)
I_0(_rfe) I_0(_rfe)
I_u2s3u1(_sc) I_u2s3u1(_sc)
I_u2s3u1(_scd) I_u2s3u1(_scd)
@ -427,6 +426,25 @@ I_u1(_syscall);
I_u1u2s3(_bbit0); I_u1u2s3(_bbit0);
I_u1u2s3(_bbit1); I_u1u2s3(_bbit1);
#ifdef CONFIG_CPU_CAVIUM_OCTEON
#include <asm/octeon/octeon.h>
void __uasminit uasm_i_pref(u32 **buf, unsigned int a, signed int b,
unsigned int c)
{
if (OCTEON_IS_MODEL(OCTEON_CN63XX_PASS1_X) && a <= 24 && a != 5)
/*
* As per erratum Core-14449, replace prefetches 0-4,
* 6-24 with 'pref 28'.
*/
build_insn(buf, insn_pref, c, 28, b);
else
build_insn(buf, insn_pref, c, a, b);
}
UASM_EXPORT_SYMBOL(uasm_i_pref);
#else
I_u2s3u1(_pref)
#endif
/* Handle labels. */ /* Handle labels. */
void __uasminit uasm_build_label(struct uasm_label **lab, u32 *addr, int lid) void __uasminit uasm_build_label(struct uasm_label **lab, u32 *addr, int lid)
{ {