UBUNTU: SAUCE: dove: erratum of VLDR instruction bug in Thumb-2 mode
Eric Miao
eric.miao at canonical.com
Thu Dec 17 01:15:42 UTC 2009
Andy,
Please pull for the fix of bug #494831, which affects boot on Dove lucid. I've
hereby combined the GIT PULL and the patch in a single mail.
The following changes since commit 7021074ea6213659aa8e04496879df5ee2fd73a3:
Andy Whitcroft (1):
UBUNTU: Ubuntu-2.6.31-701.3
are available in the git repository at:
git://kernel.ubuntu.com/ycmiao/ubuntu-lucid.git lp494831
Raymond Huang (1):
UBUNTU: SAUCE: dove: erratum of VLDR instruction bug in Thumb-2 mode
arch/arm/Kconfig | 9 +++
arch/arm/mm/alignment.c | 69 ++++++++++++++++++++++
debian.mvl-dove/config/armel/config.flavour.dove | 1 +
3 files changed, 79 insertions(+), 0 deletions(-)
commit 33473e5381c44ef11a9a391bdd97dc0e4a2f957b
Author: Raymond Huang <rhuang at marvell.com>
Date: Tue Dec 8 10:56:39 2009 +0800
UBUNTU: SAUCE: dove: erratum of VLDR instruction bug in Thumb-2 mode
BugLink: https://bugs.launchpad.net/bugs/494831
This patch enables the workaround for the Thumb-2 VLDR PJ4 erratum.
Without this patch, newly compiled armv7l + thumb2 user applications
will cause alignment traps and unhandled fault errors.
Signed-off-by: Raymond Huang <rhuang at marvell.com>
Signed-off-by: Saeed Bishara <saeed at marvell.com>
Signed-off-by: Eric Miao <eric.miao at canonical.com>
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index b8e5843..b7b0daf 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -785,6 +785,15 @@ if !MMU
source "arch/arm/Kconfig-nommu"
endif
+config MRVL_ERRATA_THUMB_VLDR
+ bool "Marvell errata: VLDR from a PC-relative address in Thumb-2
mode can cause DABT exception"
+ depends on CPU_PJ4 && ARM_THUMB && VFP
+ help
+ This option enables the workaround for the Thumb-2 VLDR PJ4 erratum.
+ If a VLDR in thumb-2 mode is not aligned to 4 and trying to load from a
+ PC-relative address, a DABT exception will happen. The workaround handles
+ the exception and load correct data to VFP register.
+
config ARM_ERRATA_411920
bool "ARM errata: Invalidation of the Instruction Cache operation can fail"
depends on CPU_V6 && !SMP
diff --git a/arch/arm/mm/alignment.c b/arch/arm/mm/alignment.c
index 03cd27d..25e8772 100644
--- a/arch/arm/mm/alignment.c
+++ b/arch/arm/mm/alignment.c
@@ -523,6 +523,64 @@ bad:
return TYPE_ERROR;
}
+#ifdef CONFIG_MRVL_ERRATA_THUMB_VLDR
+#define vmov_single(reg, val) \
+ __asm__( \
+ " .fpu vfp\n" \
+ " vmov s"#reg", %0\n" \
+ : : "r" (val))
+
+#define case_reg(reg, val) \
+ case ((reg)): \
+ vmov_single(reg, (val)); \
+ break
+
+static int
+do_alignment_thumb_vldr(unsigned long addr, unsigned long instr,
struct pt_regs *regs)
+{
+ unsigned int double_op = (instr >> 8) & 1;
+ unsigned int vd = (instr >> 12) & 15;
+ unsigned int d = (instr >> 22) & 1;
+ unsigned int reg, val;
+ unsigned int fault;
+ int i;
+
+ /* Align the address to word */
+ addr &= ~3;
+
+ if (double_op) {
+ reg = (d << 4) | vd;
+ reg = reg << 1;
+ } else
+ reg = (vd << 1) | d;
+
+ for (i = 0; i <= double_op; i++) {
+ fault = __get_user(val, (u32 *)addr);
+ if (fault)
+ goto fault;
+ switch (reg) {
+ case_reg(0, val); case_reg(1, val); case_reg(2, val); case_reg(3, val);
+ case_reg(4, val); case_reg(5, val); case_reg(6, val); case_reg(7, val);
+ case_reg(8, val); case_reg(9, val); case_reg(10, val); case_reg(11, val);
+ case_reg(12, val); case_reg(13, val); case_reg(14, val); case_reg(15, val);
+ case_reg(16, val); case_reg(17, val); case_reg(18, val); case_reg(19, val);
+ case_reg(20, val); case_reg(21, val); case_reg(22, val); case_reg(23, val);
+ case_reg(24, val); case_reg(25, val); case_reg(26, val); case_reg(27, val);
+ case_reg(28, val); case_reg(29, val); case_reg(30, val); case_reg(31, val);
+ }
+ addr += 4;
+ reg += 1;
+ }
+
+ return TYPE_DONE;
+
+ fault:
+ return TYPE_FAULT;
+}
+#undef vmov_single
+#undef case_reg
+#endif
+
/*
* Convert Thumb ld/st instruction forms to equivalent ARM instructions so
* we can reuse ARM userland alignment fault fixups for Thumb.
@@ -750,6 +808,17 @@ do_alignment(unsigned long addr, unsigned int
fsr, struct pt_regs *regs)
regs->ARM_pc += isize;
+#ifdef CONFIG_MRVL_ERRATA_THUMB_VLDR
+ if (thumb_mode(regs) && ((instr & 0xff300e00) == 0xed100a00)) {
+ type = do_alignment_thumb_vldr(addr, instr, regs);
+ if (type == TYPE_ERROR || type == TYPE_FAULT) {
+ regs->ARM_pc -= isize;
+ goto bad_or_fault;
+ }
+ return 0;
+ }
+#endif
+
switch (CODING_BITS(instr)) {
case 0x00000000: /* 3.13.4 load/store instruction extensions */
if (LDSTHD_I_BIT(instr))
diff --git a/debian.mvl-dove/config/armel/config.flavour.dove
b/debian.mvl-dove/config/armel/config.flavour.dove
index 7f406a7..7b9cf47 100644
--- a/debian.mvl-dove/config/armel/config.flavour.dove
+++ b/debian.mvl-dove/config/armel/config.flavour.dove
@@ -24,3 +24,4 @@ CONFIG_MODULE_SRCVERSION_ALL=y
CONFIG_MODVERSIONS=y
# CONFIG_MRV_PTE_IN_L2 is not set
CONFIG_MV_L2_WA_ON=y
+CONFIG_MRVL_ERRATA_THUMB_VLDR=y
More information about the kernel-team
mailing list