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:
parent
468ffde46d
commit
c9941158fd
|
@ -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))))
|
||||
cflags-$(CONFIG_CPU_CAVIUM_OCTEON) += -Wa,-march=octeon
|
||||
endif
|
||||
cflags-$(CONFIG_CAVIUM_CN63XXP1) += -Wa,-mfix-cn63xxp1
|
||||
|
||||
cflags-$(CONFIG_CPU_R4000_WORKAROUNDS) += $(call cc-option,-mfix-r4000,)
|
||||
cflags-$(CONFIG_CPU_R4400_WORKAROUNDS) += $(call cc-option,-mfix-r4400,)
|
||||
|
|
|
@ -3,6 +3,17 @@ config CAVIUM_OCTEON_SPECIFIC_OPTIONS
|
|||
depends on CPU_CAVIUM_OCTEON
|
||||
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
|
||||
bool "Build the kernel to be used as a 2nd kernel on the same chip"
|
||||
depends on CAVIUM_OCTEON_SPECIFIC_OPTIONS
|
||||
|
|
|
@ -356,8 +356,18 @@ void octeon_user_io_init(void)
|
|||
cvmmemctl.s.wbfltime = 0;
|
||||
/* R/W If set, do not put Istream in the L2 cache. */
|
||||
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
|
||||
* kernel/debug mode. */
|
||||
#if CONFIG_CAVIUM_OCTEON_CVMSEG_SIZE > 0
|
||||
|
@ -375,14 +385,13 @@ void octeon_user_io_init(void)
|
|||
* is max legal value. */
|
||||
cvmmemctl.s.lmemsz = CONFIG_CAVIUM_OCTEON_CVMSEG_SIZE;
|
||||
|
||||
write_c0_cvmmemctl(cvmmemctl.u64);
|
||||
|
||||
if (smp_processor_id() == 0)
|
||||
pr_notice("CVMSEG size: %d cache lines (%d bytes)\n",
|
||||
CONFIG_CAVIUM_OCTEON_CVMSEG_SIZE,
|
||||
CONFIG_CAVIUM_OCTEON_CVMSEG_SIZE * 128);
|
||||
|
||||
write_c0_cvmmemctl(cvmmemctl.u64);
|
||||
|
||||
/* Move the performance counter interrupts to IRQ 6 */
|
||||
cvmctl = read_c0_cvmctl();
|
||||
cvmctl &= ~(7 << 7);
|
||||
|
@ -758,6 +767,31 @@ EXPORT_SYMBOL(prom_putchar);
|
|||
|
||||
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
|
||||
cvmx_interrupt_rsl_enable();
|
||||
|
||||
|
|
|
@ -405,7 +405,6 @@ I_u1u2u3(_mfc0)
|
|||
I_u1u2u3(_mtc0)
|
||||
I_u2u1u3(_ori)
|
||||
I_u3u1u2(_or)
|
||||
I_u2s3u1(_pref)
|
||||
I_0(_rfe)
|
||||
I_u2s3u1(_sc)
|
||||
I_u2s3u1(_scd)
|
||||
|
@ -427,6 +426,25 @@ I_u1(_syscall);
|
|||
I_u1u2s3(_bbit0);
|
||||
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. */
|
||||
void __uasminit uasm_build_label(struct uasm_label **lab, u32 *addr, int lid)
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue