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))))
|
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,)
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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();
|
||||||
|
|
||||||
|
|
|
@ -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)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue