Merge branch 'master' into arm_hyp

Conflicts:
	src/arch/arm/head.S
	src/arch/arm/kernel/vspace.c
This commit is contained in:
Adrian Danis
2014-07-18 14:49:54 +10:00
5 changed files with 120 additions and 31 deletions

10
Kconfig
View File

@@ -384,4 +384,14 @@ menu "Errata"
if code containing ARM/Thumb interworking branch is replaced by different code
at the same virtual address.
config ARM_ERRATA_773022
bool "Enable workaround for 773022 Cortex-A15 (r0p0..r0p4) erratum"
depends on ARCH_ARM
depends on ARM_CORTEX_A15
default y
help
Enables a workaround for the 773022 Cortex-A15 (r0p0..r0p4) erratum. Error occurs
on rare sequences of instructions and results in the loop buffer delivering
incorrect instructions. The work around is to disable the loop buffer
endmenu

View File

@@ -64,6 +64,38 @@ void setNextPC(tcb_t *thread, word_t v);
/* Architecture specific machine operations */
/** MODIFIES: [*] */
static inline uint32_t getProcessorID(void)
{
uint32_t processor_id;
MRC("p15, 0, %0, c0, c0, 0", processor_id);
return processor_id;
}
static inline uint32_t readSystemControlRegister(void)
{
uint32_t scr;
MRC("p15, 0, %0, c1, c0, 0", scr);
return scr;
}
static inline void writeSystemControlRegister(uint32_t scr)
{
MCR("p15, 0, %0, c1, c0, 0", scr);
}
static inline uint32_t readAuxiliaryControlRegister(void)
{
uint32_t acr;
MRC("p15, 0, %0, c1, c0, 1", acr);
return acr;
}
static inline void writeAuxiliaryControlRegister(uint32_t acr)
{
MCR("p15, 0, %0, c1, c0, 1", acr);
}
/** MODIFIES: [*] */
static inline void clearExMonitor(void)
{

View File

@@ -89,36 +89,6 @@ BEGIN_FUNC(_start)
mrc p15, 0, r4, c1, c0, 0
#endif
ldr r5, =CR_BITS_SET
#ifdef ARM1136_WORKAROUND
/*
* We need to potentially work around arm1136 errata #364296 which
* can cause data cache corruption. The fix involves disabling hit-under-miss
* via an undocumented bit in the aux control register, as well as the
* FI bit in the control register. The result of enabling these two bits
* is for fast interrupts to *not* be enabled, but hit-under-miss to be
* disabled. We only need to do this for a particular revision of the
* arm1136
*/
ldr r6, =ARM1136_R0PX
/* Load processor id */
mrc p15, 0, r7, c0, c0, 0
/* Mask out bottom four part bits */
bic r7, r7, #0xf
teq r7, r6
bne 1f
/* Additionally enable the Fast Interrupts bit in the control register */
ldr r6, =BIT(CONTROL_FI)
orr r5, r5, r6
/* Set undocumented bit 31 in the auxiliary control register */
mrc p15, 0, r6, c1, c0, 1
orr r6, r6, #(1<<31)
mcr p15, 0, r6, c1, c0, 1
1:
#endif /* ARM1136_WORKAROUND */
ldr r6, =CR_BITS_CLEAR
orr r4, r4, r5
bic r4, r4, r6
@@ -142,6 +112,11 @@ BEGIN_FUNC(_start)
ldr sp, =arm_kernel_stack
add sp, sp, #(PPTR_KERNEL_STACK_TOP - PPTR_KERNEL_STACK)
/* Attempt to workaround any known ARM errata. */
push {r0-r3}
blx arm_errata
pop {r0-r3}
/* Hyp kernel always run in Hyp mode. */
#ifndef ARM_HYP
/* Initialise ABORT stack pointer */

View File

@@ -12,7 +12,8 @@ DIRECTORIES += src/arch/arm/machine
ARCH_C_SOURCES += machine/hardware.c \
machine/registerset.c \
machine/cache.c
machine/cache.c \
machine/errata.c
ifeq ($(CPU), cortex-a9)
ARCH_C_SOURCES += machine/gic_pl390.c

View File

@@ -0,0 +1,71 @@
#include <config.h>
#include <api/types.h>
#include <arch/machine.h>
#include <arch/machine/hardware.h>
/* Prototyped here as this is referenced from assembly */
void arm_errata(void);
#ifdef ARM1136_WORKAROUND
/*
* Potentially work around ARM1136 errata #364296, which can cause data
* cache corruption.
*
* The fix involves disabling hit-under-miss via an undocumented bit in
* the aux control register, as well as the FI bit in the control
* register. The result of enabling these two bits is for fast
* interrupts to *not* be enabled, but hit-under-miss to be disabled. We
* only need to do this for a particular revision of the ARM1136.
*/
BOOT_CODE static void
errata_arm1136(void)
{
/* See if we are affected by the errata. */
if ((getProcessorID() & ~0xf) == ARM1136_R0PX) {
/* Enable the Fast Interrupts bit in the control register. */
writeSystemControlRegister(
readSystemControlRegister() | BIT(CONTROL_FI));
/* Set undocumented bit 31 in the auxiliary control register */
writeAuxiliaryControlRegister(
readAuxiliaryControlRegister() | BIT(31));
}
}
#endif
#ifdef CONFIG_ARM_ERRATA_773022
/*
* There is an errata for Cortex-A15 up to r0p4 where the loop buffer
* may deliver incorrect instructions. The work around is to disable
* the loop buffer. Errata is number 773022.
*/
BOOT_CODE static void errata_armA15_773022(void)
{
/* Fetch the processor primary part number. */
uint32_t proc_id = getProcessorID();
uint32_t variant = (proc_id >> 20) & MASK(4);
uint32_t revision = proc_id & MASK(4);
uint32_t part = (proc_id >> 4) & MASK(12);
/* Check that we are running A15 and a revision upto r0p4. */
if (part == 0xc0f && variant == 0 && revision <= 4) {
/* Disable loop buffer in the auxiliary control register */
writeAuxiliaryControlRegister(
readAuxiliaryControlRegister() | BIT(1));
}
}
#endif
BOOT_CODE void __attribute__((externally_visible)) arm_errata(void)
{
#ifdef ARM1136_WORKAROUND
errata_arm1136();
#endif
#ifdef CONFIG_ARM_ERRATA_773022
(void)errata_armA15_773022;
errata_armA15_773022();
#endif
}