[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-devel] [PATCH v2 3/3] xen/arm: errata 766422: decode thumb store during data abort



From the errata document:

When a non-secure non-hypervisor memory operation instruction generates a
stage2 page table translation fault, a trap to the hypervisor will be triggered.
For an architecturally defined subset of instructions, the Hypervisor Syndrome
Register (HSR) will have the Instruction Syndrome Valid (ISV) bit set to 1âb1,
and the Rt field should reflect the source register (for stores) or destination
register for loads.
On Cortex-A15, for Thumb and ThumbEE stores, the Rt value may be incorrect
and should not be used, even if the ISV bit is set. All loads, and all ARM
instruction set loads and stores, will have the correct Rt value if the ISV
bit is set.

To avoid this issue, Xen needs to decode thumb store instruction and update
the transfer register.

Signed-off-by: Julien Grall <julien.grall@xxxxxxxxxx>

---
    Changes in v2:
        - Only decode the instruction on affected processor
        - Handle ARM 32-bit instruction in read_instruction
---
 xen/arch/arm/traps.c                  |   44 +++++++++++++++++++++++++++++++++
 xen/include/asm-arm/arm32/processor.h |    3 +++
 xen/include/asm-arm/arm64/processor.h |    2 ++
 3 files changed, 49 insertions(+)

diff --git a/xen/arch/arm/traps.c b/xen/arch/arm/traps.c
index d6dc37d..3aa2b8c 100644
--- a/xen/arch/arm/traps.c
+++ b/xen/arch/arm/traps.c
@@ -35,6 +35,7 @@
 #include <asm/regs.h>
 #include <asm/cpregs.h>
 #include <asm/psci.h>
+#include <asm/guest_access.h>
 
 #include "io.h"
 #include "vtimer.h"
@@ -996,6 +997,28 @@ done:
     if (first) unmap_domain_page(first);
 }
 
+static int read_instruction(struct cpu_user_regs *regs, unsigned len,
+                            uint32_t *instr)
+{
+    int rc;
+
+    rc = raw_copy_from_guest(instr, (void * __user)regs->pc, (len ? 4 : 2));
+
+    if ( rc )
+        return rc;
+
+    if ( !len ) /* 16-bit instruction */
+        *instr &= 0xffff;
+    else /* 32-bit instruction */
+    {
+        /* THUMB 32-bit instruction consisting of 2 consecutive halfwords */
+        if ( regs->cpsr & PSR_THUMB )
+            *instr = (*instr & 0xffff) << 16 | (*instr & 0xffff0000) >> 16;
+    }
+
+    return 0;
+}
+
 static void do_trap_data_abort_guest(struct cpu_user_regs *regs,
                                      struct hsr_dabt dabt)
 {
@@ -1021,6 +1044,27 @@ static void do_trap_data_abort_guest(struct 
cpu_user_regs *regs,
     if ( !dabt.valid )
         goto bad_data_abort;
 
+    /*
+     * Errata 766422: Thumb store translation fault to Hypervisor may
+     * not have correct HSR Rt value.
+     */
+    if ( cpu_has_errata_766422() && (regs->cpsr & PSR_THUMB) && dabt.write )
+    {
+        uint32_t instr = 0;
+
+        rc = read_instruction(regs, dabt.len, &instr);
+        if ( rc )
+            goto bad_data_abort;
+
+        /* Retrieve the transfer register from the instruction */
+        if ( dabt.len )
+            /* With 32-bit store instruction, the register is in [12..15] */
+            info.dabt.reg = (instr & 0xf000) >> 12;
+        else
+            /* With 16-bit store instruction, the register is in [0..3] */
+            info.dabt.reg = instr & 0x7;
+    }
+
     if (handle_mmio(&info))
     {
         regs->pc += dabt.len ? 4 : 2;
diff --git a/xen/include/asm-arm/arm32/processor.h 
b/xen/include/asm-arm/arm32/processor.h
index b266252..bc82fbc 100644
--- a/xen/include/asm-arm/arm32/processor.h
+++ b/xen/include/asm-arm/arm32/processor.h
@@ -111,6 +111,9 @@ struct cpu_user_regs
 #define READ_SYSREG(R...)       READ_SYSREG32(R)
 #define WRITE_SYSREG(V, R...)   WRITE_SYSREG32(V, R)
 
+/* Errata 766422: only Cortex A15 r0p4 is affected */
+#define cpu_has_errata_766422() (current_cpu_data.midr.bits == 0x410fc0f4)
+
 #endif /* __ASSEMBLY__ */
 
 #endif /* __ASM_ARM_ARM32_PROCESSOR_H */
diff --git a/xen/include/asm-arm/arm64/processor.h 
b/xen/include/asm-arm/arm64/processor.h
index d9fbcb2..ac7f1bd 100644
--- a/xen/include/asm-arm/arm64/processor.h
+++ b/xen/include/asm-arm/arm64/processor.h
@@ -105,6 +105,8 @@ struct cpu_user_regs
 #define READ_SYSREG(name)     READ_SYSREG64(name)
 #define WRITE_SYSREG(v, name) WRITE_SYSREG64(v, name)
 
+#define cpu_has_errata_766422() 0
+
 #endif /* __ASSEMBLY__ */
 
 #endif /* __ASM_ARM_ARM64_PROCESSOR_H */
-- 
1.7.10.4


_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
http://lists.xen.org/xen-devel

 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.