Commit 8294fec1 authored by Nick Hawkins's avatar Nick Hawkins Committed by Russell King (Oracle)
Browse files

ARM: 9206/1: A9: Add ARM ERRATA 764319 workaround (Updated)



Enable the workaround for the 764319 Cortex A-9 erratum.
CP14 read accesses to the DBGPRSR and DBGOSLSR registers generate an
unexpected Undefined Instruction exception when the DBGSWENABLE external
pin is set to 0, even when the CP14 accesses are performed from a
privileged mode. The work around catches the exception in a way
the kernel does not stop execution with the use of undef_hook. This
has been found to effect the HPE GXP SoC.

Signed-off-by: default avatarNick Hawkins <nick.hawkins@hpe.com>
Reviewed-by: default avatarArnd Bergmann <arnd@arndb.de>
Signed-off-by: default avatarRussell King (Oracle) <rmk+kernel@armlinux.org.uk>
parent ad12c2f1
Loading
Loading
Loading
Loading
+11 −0
Original line number Diff line number Diff line
@@ -972,6 +972,17 @@ config ARM_ERRATA_764369
	  relevant cache maintenance functions and sets a specific bit
	  in the diagnostic control register of the SCU.

config ARM_ERRATA_764319
	bool "ARM errata: Read to DBGPRSR and DBGOSLSR may generate Undefined instruction"
	depends on CPU_V7
	help
	  This option enables the workaround for the 764319 Cortex A-9 erratum.
	  CP14 read accesses to the DBGPRSR and DBGOSLSR registers generate an
	  unexpected Undefined Instruction exception when the DBGSWENABLE
	  external pin is set to 0, even when the CP14 accesses are performed
	  from a privileged mode. This work around catches the exception in a
	  way the kernel does not stop execution.

config ARM_ERRATA_775420
       bool "ARM errata: A data cache maintenance operation which aborts, might lead to deadlock"
       depends on CPU_V7
+26 −0
Original line number Diff line number Diff line
@@ -941,6 +941,23 @@ static int hw_breakpoint_pending(unsigned long addr, unsigned int fsr,
	return ret;
}

#ifdef CONFIG_ARM_ERRATA_764319
static int oslsr_fault;

static int debug_oslsr_trap(struct pt_regs *regs, unsigned int instr)
{
	oslsr_fault = 1;
	instruction_pointer(regs) += 4;
	return 0;
}

static struct undef_hook debug_oslsr_hook = {
	.instr_mask  = 0xffffffff,
	.instr_val = 0xee115e91,
	.fn = debug_oslsr_trap,
};
#endif

/*
 * One-time initialisation.
 */
@@ -974,7 +991,16 @@ static bool core_has_os_save_restore(void)
	case ARM_DEBUG_ARCH_V7_1:
		return true;
	case ARM_DEBUG_ARCH_V7_ECP14:
#ifdef CONFIG_ARM_ERRATA_764319
		oslsr_fault = 0;
		register_undef_hook(&debug_oslsr_hook);
		ARM_DBG_READ(c1, c1, 4, oslsr);
		unregister_undef_hook(&debug_oslsr_hook);
		if (oslsr_fault)
			return false;
#else
		ARM_DBG_READ(c1, c1, 4, oslsr);
#endif
		if (oslsr & ARM_OSLSR_OSLM0)
			return true;
		fallthrough;