Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

David Daney and committed by
Ralf Baechle
c9941158 468ffde4

+69 -5
+1
arch/mips/Makefile
··· 156 156 ifeq (,$(findstring march=octeon, $(cflags-$(CONFIG_CPU_CAVIUM_OCTEON)))) 157 157 cflags-$(CONFIG_CPU_CAVIUM_OCTEON) += -Wa,-march=octeon 158 158 endif 159 + cflags-$(CONFIG_CAVIUM_CN63XXP1) += -Wa,-mfix-cn63xxp1 159 160 160 161 cflags-$(CONFIG_CPU_R4000_WORKAROUNDS) += $(call cc-option,-mfix-r4000,) 161 162 cflags-$(CONFIG_CPU_R4400_WORKAROUNDS) += $(call cc-option,-mfix-r4400,)
+11
arch/mips/cavium-octeon/Kconfig
··· 3 3 depends on CPU_CAVIUM_OCTEON 4 4 default "y" 5 5 6 + config CAVIUM_CN63XXP1 7 + bool "Enable CN63XXP1 errata worarounds" 8 + depends on CAVIUM_OCTEON_SPECIFIC_OPTIONS 9 + default "n" 10 + help 11 + The CN63XXP1 chip requires build time workarounds to 12 + function reliably, select this option to enable them. These 13 + workarounds will cause a slight decrease in performance on 14 + non-CN63XXP1 hardware, so it is recommended to select "n" 15 + unless it is known the workarounds are needed. 16 + 6 17 config CAVIUM_OCTEON_2ND_KERNEL 7 18 bool "Build the kernel to be used as a 2nd kernel on the same chip" 8 19 depends on CAVIUM_OCTEON_SPECIFIC_OPTIONS
+38 -4
arch/mips/cavium-octeon/setup.c
··· 356 356 cvmmemctl.s.wbfltime = 0; 357 357 /* R/W If set, do not put Istream in the L2 cache. */ 358 358 cvmmemctl.s.istrnol2 = 0; 359 - /* R/W The write buffer threshold. */ 360 - cvmmemctl.s.wbthresh = 10; 359 + 360 + /* 361 + * R/W The write buffer threshold. As per erratum Core-14752 362 + * for CN63XX, a sc/scd might fail if the write buffer is 363 + * full. Lowering WBTHRESH greatly lowers the chances of the 364 + * write buffer ever being full and triggering the erratum. 365 + */ 366 + if (OCTEON_IS_MODEL(OCTEON_CN63XX_PASS1_X)) 367 + cvmmemctl.s.wbthresh = 4; 368 + else 369 + cvmmemctl.s.wbthresh = 10; 370 + 361 371 /* R/W If set, CVMSEG is available for loads/stores in 362 372 * kernel/debug mode. */ 363 373 #if CONFIG_CAVIUM_OCTEON_CVMSEG_SIZE > 0 ··· 385 375 * is max legal value. */ 386 376 cvmmemctl.s.lmemsz = CONFIG_CAVIUM_OCTEON_CVMSEG_SIZE; 387 377 378 + write_c0_cvmmemctl(cvmmemctl.u64); 388 379 389 380 if (smp_processor_id() == 0) 390 381 pr_notice("CVMSEG size: %d cache lines (%d bytes)\n", 391 382 CONFIG_CAVIUM_OCTEON_CVMSEG_SIZE, 392 383 CONFIG_CAVIUM_OCTEON_CVMSEG_SIZE * 128); 393 - 394 - write_c0_cvmmemctl(cvmmemctl.u64); 395 384 396 385 /* Move the performance counter interrupts to IRQ 6 */ 397 386 cvmctl = read_c0_cvmctl(); ··· 767 758 768 759 void prom_free_prom_memory(void) 769 760 { 761 + if (OCTEON_IS_MODEL(OCTEON_CN63XX_PASS1_X)) { 762 + /* Check for presence of Core-14449 fix. */ 763 + u32 insn; 764 + u32 *foo; 765 + 766 + foo = &insn; 767 + 768 + asm volatile("# before" : : : "memory"); 769 + prefetch(foo); 770 + asm volatile( 771 + ".set push\n\t" 772 + ".set noreorder\n\t" 773 + "bal 1f\n\t" 774 + "nop\n" 775 + "1:\tlw %0,-12($31)\n\t" 776 + ".set pop\n\t" 777 + : "=r" (insn) : : "$31", "memory"); 778 + 779 + if ((insn >> 26) != 0x33) 780 + panic("No PREF instruction at Core-14449 probe point.\n"); 781 + 782 + if (((insn >> 16) & 0x1f) != 28) 783 + panic("Core-14449 WAR not in place (%04x).\n" 784 + "Please build kernel with proper options (CONFIG_CAVIUM_CN63XXP1).\n", insn); 785 + } 770 786 #ifdef CONFIG_CAVIUM_DECODE_RSL 771 787 cvmx_interrupt_rsl_enable(); 772 788
+19 -1
arch/mips/mm/uasm.c
··· 405 405 I_u1u2u3(_mtc0) 406 406 I_u2u1u3(_ori) 407 407 I_u3u1u2(_or) 408 - I_u2s3u1(_pref) 409 408 I_0(_rfe) 410 409 I_u2s3u1(_sc) 411 410 I_u2s3u1(_scd) ··· 425 426 I_u1(_syscall); 426 427 I_u1u2s3(_bbit0); 427 428 I_u1u2s3(_bbit1); 429 + 430 + #ifdef CONFIG_CPU_CAVIUM_OCTEON 431 + #include <asm/octeon/octeon.h> 432 + void __uasminit uasm_i_pref(u32 **buf, unsigned int a, signed int b, 433 + unsigned int c) 434 + { 435 + if (OCTEON_IS_MODEL(OCTEON_CN63XX_PASS1_X) && a <= 24 && a != 5) 436 + /* 437 + * As per erratum Core-14449, replace prefetches 0-4, 438 + * 6-24 with 'pref 28'. 439 + */ 440 + build_insn(buf, insn_pref, c, 28, b); 441 + else 442 + build_insn(buf, insn_pref, c, a, b); 443 + } 444 + UASM_EXPORT_SYMBOL(uasm_i_pref); 445 + #else 446 + I_u2s3u1(_pref) 447 + #endif 428 448 429 449 /* Handle labels. */ 430 450 void __uasminit uasm_build_label(struct uasm_label **lab, u32 *addr, int lid)