diff mbox

UBUNTU: SAUCE: dove: erratum of VLDR instruction bug in Thumb-2 mode

Message ID f17812d70912161715h6855bde4t5b3db7f62514155@mail.gmail.com
State Accepted
Delegated to: Andy Whitcroft
Headers show

Commit Message

Eric Miao Dec. 17, 2009, 1:15 a.m. UTC
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@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@marvell.com>
    Signed-off-by: Saeed Bishara <saeed@marvell.com>
    Signed-off-by: Eric Miao <eric.miao@canonical.com>

Comments

Andy Whitcroft Dec. 17, 2009, 9:13 a.m. UTC | #1
Applied to Lucid.

-apw
Stefan Bader Dec. 19, 2009, 8:29 a.m. UTC | #2
Also applied to Karmic and uploaded.
diff mbox

Patch

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