]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
4.5-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sun, 29 May 2016 21:42:48 +0000 (14:42 -0700)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sun, 29 May 2016 21:42:48 +0000 (14:42 -0700)
added patches:
arm-arm64-kvm-enforce-break-before-make-on-stage-2-page-tables.patch
arm64-cpuinfo-missing-null-terminator-in-compat_hwcap_str.patch
arm64-ensure-pmd_present-returns-false-after-pmd_mknotpresent.patch
arm64-fix-typo-in-the-pmdp_huge_get_and_clear-definition.patch
arm64-implement-pmdp_set_access_flags-for-hardware-af-dbm.patch
arm64-implement-ptep_set_access_flags-for-hardware-af-dbm.patch
kvm-arm64-fix-ec-field-in-inject_abt64.patch

queue-4.5/arm-arm64-kvm-enforce-break-before-make-on-stage-2-page-tables.patch [new file with mode: 0644]
queue-4.5/arm64-cpuinfo-missing-null-terminator-in-compat_hwcap_str.patch [new file with mode: 0644]
queue-4.5/arm64-ensure-pmd_present-returns-false-after-pmd_mknotpresent.patch [new file with mode: 0644]
queue-4.5/arm64-fix-typo-in-the-pmdp_huge_get_and_clear-definition.patch [new file with mode: 0644]
queue-4.5/arm64-implement-pmdp_set_access_flags-for-hardware-af-dbm.patch [new file with mode: 0644]
queue-4.5/arm64-implement-ptep_set_access_flags-for-hardware-af-dbm.patch [new file with mode: 0644]
queue-4.5/kvm-arm64-fix-ec-field-in-inject_abt64.patch [new file with mode: 0644]

diff --git a/queue-4.5/arm-arm64-kvm-enforce-break-before-make-on-stage-2-page-tables.patch b/queue-4.5/arm-arm64-kvm-enforce-break-before-make-on-stage-2-page-tables.patch
new file mode 100644 (file)
index 0000000..be01ed0
--- /dev/null
@@ -0,0 +1,63 @@
+From d4b9e0790aa764c0b01e18d4e8d33e93ba36d51f Mon Sep 17 00:00:00 2001
+From: Marc Zyngier <marc.zyngier@arm.com>
+Date: Thu, 28 Apr 2016 16:16:31 +0100
+Subject: arm/arm64: KVM: Enforce Break-Before-Make on Stage-2 page tables
+
+From: Marc Zyngier <marc.zyngier@arm.com>
+
+commit d4b9e0790aa764c0b01e18d4e8d33e93ba36d51f upstream.
+
+The ARM architecture mandates that when changing a page table entry
+from a valid entry to another valid entry, an invalid entry is first
+written, TLB invalidated, and only then the new entry being written.
+
+The current code doesn't respect this, directly writing the new
+entry and only then invalidating TLBs. Let's fix it up.
+
+Reported-by: Christoffer Dall <christoffer.dall@linaro.org>
+Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
+Signed-off-by: Christoffer Dall <christoffer.dall@linaro.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ arch/arm/kvm/mmu.c |   17 +++++++++++------
+ 1 file changed, 11 insertions(+), 6 deletions(-)
+
+--- a/arch/arm/kvm/mmu.c
++++ b/arch/arm/kvm/mmu.c
+@@ -886,11 +886,14 @@ static int stage2_set_pmd_huge(struct kv
+       VM_BUG_ON(pmd_present(*pmd) && pmd_pfn(*pmd) != pmd_pfn(*new_pmd));
+       old_pmd = *pmd;
+-      kvm_set_pmd(pmd, *new_pmd);
+-      if (pmd_present(old_pmd))
++      if (pmd_present(old_pmd)) {
++              pmd_clear(pmd);
+               kvm_tlb_flush_vmid_ipa(kvm, addr);
+-      else
++      } else {
+               get_page(virt_to_page(pmd));
++      }
++
++      kvm_set_pmd(pmd, *new_pmd);
+       return 0;
+ }
+@@ -939,12 +942,14 @@ static int stage2_set_pte(struct kvm *kv
+       /* Create 2nd stage page table mapping - Level 3 */
+       old_pte = *pte;
+-      kvm_set_pte(pte, *new_pte);
+-      if (pte_present(old_pte))
++      if (pte_present(old_pte)) {
++              kvm_set_pte(pte, __pte(0));
+               kvm_tlb_flush_vmid_ipa(kvm, addr);
+-      else
++      } else {
+               get_page(virt_to_page(pte));
++      }
++      kvm_set_pte(pte, *new_pte);
+       return 0;
+ }
diff --git a/queue-4.5/arm64-cpuinfo-missing-null-terminator-in-compat_hwcap_str.patch b/queue-4.5/arm64-cpuinfo-missing-null-terminator-in-compat_hwcap_str.patch
new file mode 100644 (file)
index 0000000..0b1a13b
--- /dev/null
@@ -0,0 +1,44 @@
+From f228b494e56d949be8d8ea09d4f973d1979201bf Mon Sep 17 00:00:00 2001
+From: Julien Grall <julien.grall@arm.com>
+Date: Tue, 10 May 2016 15:40:31 +0100
+Subject: arm64: cpuinfo: Missing NULL terminator in compat_hwcap_str
+
+From: Julien Grall <julien.grall@arm.com>
+
+commit f228b494e56d949be8d8ea09d4f973d1979201bf upstream.
+
+The loop that browses the array compat_hwcap_str will stop when a NULL
+is encountered, however NULL is missing at the end of array. This will
+lead to overrun until a NULL is found somewhere in the following memory.
+In reality, this works out because the compat_hwcap2_str array tends to
+follow immediately in memory, and that *is* terminated correctly.
+Furthermore, the unsigned int compat_elf_hwcap is checked before
+printing each capability, so we end up doing the right thing because
+the size of the two arrays is less than 32. Still, this is an obvious
+mistake and should be fixed.
+
+Note for backporting: commit 12d11817eaafa414 ("arm64: Move
+/proc/cpuinfo handling code") moved this code in v4.4. Prior to that
+commit, the same change should be made in arch/arm64/kernel/setup.c.
+
+Fixes: 44b82b7700d0 "arm64: Fix up /proc/cpuinfo"
+Signed-off-by: Julien Grall <julien.grall@arm.com>
+Signed-off-by: Will Deacon <will.deacon@arm.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ arch/arm64/kernel/cpuinfo.c |    3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+--- a/arch/arm64/kernel/cpuinfo.c
++++ b/arch/arm64/kernel/cpuinfo.c
+@@ -85,7 +85,8 @@ static const char *const compat_hwcap_st
+       "idivt",
+       "vfpd32",
+       "lpae",
+-      "evtstrm"
++      "evtstrm",
++      NULL
+ };
+ static const char *const compat_hwcap2_str[] = {
diff --git a/queue-4.5/arm64-ensure-pmd_present-returns-false-after-pmd_mknotpresent.patch b/queue-4.5/arm64-ensure-pmd_present-returns-false-after-pmd_mknotpresent.patch
new file mode 100644 (file)
index 0000000..760faa1
--- /dev/null
@@ -0,0 +1,70 @@
+From 5bb1cc0ff9a6b68871970737e6c4c16919928d8b Mon Sep 17 00:00:00 2001
+From: Catalin Marinas <catalin.marinas@arm.com>
+Date: Thu, 5 May 2016 10:44:02 +0100
+Subject: arm64: Ensure pmd_present() returns false after pmd_mknotpresent()
+
+From: Catalin Marinas <catalin.marinas@arm.com>
+
+commit 5bb1cc0ff9a6b68871970737e6c4c16919928d8b upstream.
+
+Currently, pmd_present() only checks for a non-zero value, returning
+true even after pmd_mknotpresent() (which only clears the type bits).
+This patch converts pmd_present() to using pte_present(), similar to the
+other pmd_*() checks. As a side effect, it will return true for
+PROT_NONE mappings, though they are not yet used by the kernel with
+transparent huge pages.
+
+For consistency, also change pmd_mknotpresent() to only clear the
+PMD_SECT_VALID bit, even though the PMD_TABLE_BIT is already 0 for block
+mappings (no functional change). The unused PMD_SECT_PROT_NONE
+definition is removed as transparent huge pages use the pte page prot
+values.
+
+Fixes: 9c7e535fcc17 ("arm64: mm: Route pmd thp functions through pte equivalents")
+Reviewed-by: Will Deacon <will.deacon@arm.com>
+Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
+Signed-off-by: Will Deacon <will.deacon@arm.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ arch/arm64/include/asm/pgtable-hwdef.h |    1 -
+ arch/arm64/include/asm/pgtable.h       |    4 ++--
+ 2 files changed, 2 insertions(+), 3 deletions(-)
+
+--- a/arch/arm64/include/asm/pgtable-hwdef.h
++++ b/arch/arm64/include/asm/pgtable-hwdef.h
+@@ -133,7 +133,6 @@
+  * Section
+  */
+ #define PMD_SECT_VALID                (_AT(pmdval_t, 1) << 0)
+-#define PMD_SECT_PROT_NONE    (_AT(pmdval_t, 1) << 58)
+ #define PMD_SECT_USER         (_AT(pmdval_t, 1) << 6)         /* AP[1] */
+ #define PMD_SECT_RDONLY               (_AT(pmdval_t, 1) << 7)         /* AP[2] */
+ #define PMD_SECT_S            (_AT(pmdval_t, 3) << 8)
+--- a/arch/arm64/include/asm/pgtable.h
++++ b/arch/arm64/include/asm/pgtable.h
+@@ -356,6 +356,7 @@ static inline pgprot_t mk_sect_prot(pgpr
+ #define pmd_trans_huge(pmd)   (pmd_val(pmd) && !(pmd_val(pmd) & PMD_TABLE_BIT))
+ #endif /* CONFIG_TRANSPARENT_HUGEPAGE */
++#define pmd_present(pmd)      pte_present(pmd_pte(pmd))
+ #define pmd_dirty(pmd)                pte_dirty(pmd_pte(pmd))
+ #define pmd_young(pmd)                pte_young(pmd_pte(pmd))
+ #define pmd_wrprotect(pmd)    pte_pmd(pte_wrprotect(pmd_pte(pmd)))
+@@ -364,7 +365,7 @@ static inline pgprot_t mk_sect_prot(pgpr
+ #define pmd_mkclean(pmd)       pte_pmd(pte_mkclean(pmd_pte(pmd)))
+ #define pmd_mkdirty(pmd)      pte_pmd(pte_mkdirty(pmd_pte(pmd)))
+ #define pmd_mkyoung(pmd)      pte_pmd(pte_mkyoung(pmd_pte(pmd)))
+-#define pmd_mknotpresent(pmd) (__pmd(pmd_val(pmd) & ~PMD_TYPE_MASK))
++#define pmd_mknotpresent(pmd) (__pmd(pmd_val(pmd) & ~PMD_SECT_VALID))
+ #define __HAVE_ARCH_PMD_WRITE
+ #define pmd_write(pmd)                pte_write(pmd_pte(pmd))
+@@ -403,7 +404,6 @@ extern pgprot_t phys_mem_access_prot(str
+                                    unsigned long size, pgprot_t vma_prot);
+ #define pmd_none(pmd)         (!pmd_val(pmd))
+-#define pmd_present(pmd)      (pmd_val(pmd))
+ #define pmd_bad(pmd)          (!(pmd_val(pmd) & 2))
diff --git a/queue-4.5/arm64-fix-typo-in-the-pmdp_huge_get_and_clear-definition.patch b/queue-4.5/arm64-fix-typo-in-the-pmdp_huge_get_and_clear-definition.patch
new file mode 100644 (file)
index 0000000..4c30cd4
--- /dev/null
@@ -0,0 +1,40 @@
+From 911f56eeb87ee378f5e215469268a7a2f68a5a8a Mon Sep 17 00:00:00 2001
+From: Catalin Marinas <catalin.marinas@arm.com>
+Date: Thu, 5 May 2016 10:43:59 +0100
+Subject: arm64: Fix typo in the pmdp_huge_get_and_clear() definition
+
+From: Catalin Marinas <catalin.marinas@arm.com>
+
+commit 911f56eeb87ee378f5e215469268a7a2f68a5a8a upstream.
+
+With hardware AF/DBM support, pmd modifications (transparent huge pages)
+should be performed atomically using load/store exclusive. The initial
+patches defined the get-and-clear function and __HAVE_ARCH_* macro
+without the "huge" word, leaving the pmdp_huge_get_and_clear() to the
+default, non-atomic implementation.
+
+Fixes: 2f4b829c625e ("arm64: Add support for hardware updates of the access and dirty pte bits")
+Reviewed-by: Will Deacon <will.deacon@arm.com>
+Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
+Signed-off-by: Will Deacon <will.deacon@arm.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ arch/arm64/include/asm/pgtable.h |    6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+--- a/arch/arm64/include/asm/pgtable.h
++++ b/arch/arm64/include/asm/pgtable.h
+@@ -599,9 +599,9 @@ static inline pte_t ptep_get_and_clear(s
+ }
+ #ifdef CONFIG_TRANSPARENT_HUGEPAGE
+-#define __HAVE_ARCH_PMDP_GET_AND_CLEAR
+-static inline pmd_t pmdp_get_and_clear(struct mm_struct *mm,
+-                                     unsigned long address, pmd_t *pmdp)
++#define __HAVE_ARCH_PMDP_HUGE_GET_AND_CLEAR
++static inline pmd_t pmdp_huge_get_and_clear(struct mm_struct *mm,
++                                          unsigned long address, pmd_t *pmdp)
+ {
+       return pte_pmd(ptep_get_and_clear(mm, address, (pte_t *)pmdp));
+ }
diff --git a/queue-4.5/arm64-implement-pmdp_set_access_flags-for-hardware-af-dbm.patch b/queue-4.5/arm64-implement-pmdp_set_access_flags-for-hardware-af-dbm.patch
new file mode 100644 (file)
index 0000000..d7e2d99
--- /dev/null
@@ -0,0 +1,45 @@
+From 282aa7051b0169991b34716f0f22d9c2f59c46c4 Mon Sep 17 00:00:00 2001
+From: Catalin Marinas <catalin.marinas@arm.com>
+Date: Thu, 5 May 2016 10:44:00 +0100
+Subject: arm64: Implement pmdp_set_access_flags() for hardware AF/DBM
+
+From: Catalin Marinas <catalin.marinas@arm.com>
+
+commit 282aa7051b0169991b34716f0f22d9c2f59c46c4 upstream.
+
+The update to the accessed or dirty states for block mappings must be
+done atomically on hardware with support for automatic AF/DBM. The
+ptep_set_access_flags() function has been fixed as part of commit
+66dbd6e61a52 ("arm64: Implement ptep_set_access_flags() for hardware
+AF/DBM"). This patch brings pmdp_set_access_flags() in line with the pte
+counterpart.
+
+Fixes: 2f4b829c625e ("arm64: Add support for hardware updates of the access and dirty pte bits")
+Reviewed-by: Will Deacon <will.deacon@arm.com>
+Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
+Signed-off-by: Will Deacon <will.deacon@arm.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ arch/arm64/include/asm/pgtable.h |   10 ++++++++++
+ 1 file changed, 10 insertions(+)
+
+--- a/arch/arm64/include/asm/pgtable.h
++++ b/arch/arm64/include/asm/pgtable.h
+@@ -552,6 +552,16 @@ extern int ptep_set_access_flags(struct
+                                unsigned long address, pte_t *ptep,
+                                pte_t entry, int dirty);
++#ifdef CONFIG_TRANSPARENT_HUGEPAGE
++#define __HAVE_ARCH_PMDP_SET_ACCESS_FLAGS
++static inline int pmdp_set_access_flags(struct vm_area_struct *vma,
++                                      unsigned long address, pmd_t *pmdp,
++                                      pmd_t entry, int dirty)
++{
++      return ptep_set_access_flags(vma, address, (pte_t *)pmdp, pmd_pte(entry), dirty);
++}
++#endif
++
+ /*
+  * Atomic pte/pmd modifications.
+  */
diff --git a/queue-4.5/arm64-implement-ptep_set_access_flags-for-hardware-af-dbm.patch b/queue-4.5/arm64-implement-ptep_set_access_flags-for-hardware-af-dbm.patch
new file mode 100644 (file)
index 0000000..dcbabbd
--- /dev/null
@@ -0,0 +1,131 @@
+From 66dbd6e61a526ae7d11a208238ae2c17e5cacb6b Mon Sep 17 00:00:00 2001
+From: Catalin Marinas <catalin.marinas@arm.com>
+Date: Wed, 13 Apr 2016 16:01:22 +0100
+Subject: arm64: Implement ptep_set_access_flags() for hardware AF/DBM
+
+From: Catalin Marinas <catalin.marinas@arm.com>
+
+commit 66dbd6e61a526ae7d11a208238ae2c17e5cacb6b upstream.
+
+When hardware updates of the access and dirty states are enabled, the
+default ptep_set_access_flags() implementation based on calling
+set_pte_at() directly is potentially racy. This triggers the "racy dirty
+state clearing" warning in set_pte_at() because an existing writable PTE
+is overridden with a clean entry.
+
+There are two main scenarios for this situation:
+
+1. The CPU getting an access fault does not support hardware updates of
+   the access/dirty flags. However, a different agent in the system
+   (e.g. SMMU) can do this, therefore overriding a writable entry with a
+   clean one could potentially lose the automatically updated dirty
+   status
+
+2. A more complex situation is possible when all CPUs support hardware
+   AF/DBM:
+
+   a) Initial state: shareable + writable vma and pte_none(pte)
+   b) Read fault taken by two threads of the same process on different
+      CPUs
+   c) CPU0 takes the mmap_sem and proceeds to handling the fault. It
+      eventually reaches do_set_pte() which sets a writable + clean pte.
+      CPU0 releases the mmap_sem
+   d) CPU1 acquires the mmap_sem and proceeds to handle_pte_fault(). The
+      pte entry it reads is present, writable and clean and it continues
+      to pte_mkyoung()
+   e) CPU1 calls ptep_set_access_flags()
+
+   If between (d) and (e) the hardware (another CPU) updates the dirty
+   state (clears PTE_RDONLY), CPU1 will override the PTR_RDONLY bit
+   marking the entry clean again.
+
+This patch implements an arm64-specific ptep_set_access_flags() function
+to perform an atomic update of the PTE flags.
+
+Fixes: 2f4b829c625e ("arm64: Add support for hardware updates of the access and dirty pte bits")
+Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
+Reported-by: Ming Lei <tom.leiming@gmail.com>
+Tested-by: Julien Grall <julien.grall@arm.com>
+Cc: Will Deacon <will.deacon@arm.com>
+[will: reworded comment]
+Signed-off-by: Will Deacon <will.deacon@arm.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ arch/arm64/include/asm/pgtable.h |    5 +++
+ arch/arm64/mm/fault.c            |   50 +++++++++++++++++++++++++++++++++++++++
+ 2 files changed, 55 insertions(+)
+
+--- a/arch/arm64/include/asm/pgtable.h
++++ b/arch/arm64/include/asm/pgtable.h
+@@ -547,6 +547,11 @@ static inline pmd_t pmd_modify(pmd_t pmd
+ }
+ #ifdef CONFIG_ARM64_HW_AFDBM
++#define __HAVE_ARCH_PTEP_SET_ACCESS_FLAGS
++extern int ptep_set_access_flags(struct vm_area_struct *vma,
++                               unsigned long address, pte_t *ptep,
++                               pte_t entry, int dirty);
++
+ /*
+  * Atomic pte/pmd modifications.
+  */
+--- a/arch/arm64/mm/fault.c
++++ b/arch/arm64/mm/fault.c
+@@ -81,6 +81,56 @@ void show_pte(struct mm_struct *mm, unsi
+       printk("\n");
+ }
++#ifdef CONFIG_ARM64_HW_AFDBM
++/*
++ * This function sets the access flags (dirty, accessed), as well as write
++ * permission, and only to a more permissive setting.
++ *
++ * It needs to cope with hardware update of the accessed/dirty state by other
++ * agents in the system and can safely skip the __sync_icache_dcache() call as,
++ * like set_pte_at(), the PTE is never changed from no-exec to exec here.
++ *
++ * Returns whether or not the PTE actually changed.
++ */
++int ptep_set_access_flags(struct vm_area_struct *vma,
++                        unsigned long address, pte_t *ptep,
++                        pte_t entry, int dirty)
++{
++      pteval_t old_pteval;
++      unsigned int tmp;
++
++      if (pte_same(*ptep, entry))
++              return 0;
++
++      /* only preserve the access flags and write permission */
++      pte_val(entry) &= PTE_AF | PTE_WRITE | PTE_DIRTY;
++
++      /*
++       * PTE_RDONLY is cleared by default in the asm below, so set it in
++       * back if necessary (read-only or clean PTE).
++       */
++      if (!pte_write(entry) || !dirty)
++              pte_val(entry) |= PTE_RDONLY;
++
++      /*
++       * Setting the flags must be done atomically to avoid racing with the
++       * hardware update of the access/dirty state.
++       */
++      asm volatile("//        ptep_set_access_flags\n"
++      "       prfm    pstl1strm, %2\n"
++      "1:     ldxr    %0, %2\n"
++      "       and     %0, %0, %3              // clear PTE_RDONLY\n"
++      "       orr     %0, %0, %4              // set flags\n"
++      "       stxr    %w1, %0, %2\n"
++      "       cbnz    %w1, 1b\n"
++      : "=&r" (old_pteval), "=&r" (tmp), "+Q" (pte_val(*ptep))
++      : "L" (~PTE_RDONLY), "r" (pte_val(entry)));
++
++      flush_tlb_fix_spurious_fault(vma, address);
++      return 1;
++}
++#endif
++
+ /*
+  * The kernel tried to access some page that wasn't present.
+  */
diff --git a/queue-4.5/kvm-arm64-fix-ec-field-in-inject_abt64.patch b/queue-4.5/kvm-arm64-fix-ec-field-in-inject_abt64.patch
new file mode 100644 (file)
index 0000000..b483197
--- /dev/null
@@ -0,0 +1,33 @@
+From e4fe9e7dc3828bf6a5714eb3c55aef6260d823a2 Mon Sep 17 00:00:00 2001
+From: Matt Evans <matt.evans@arm.com>
+Date: Mon, 16 May 2016 13:54:56 +0100
+Subject: kvm: arm64: Fix EC field in inject_abt64
+
+From: Matt Evans <matt.evans@arm.com>
+
+commit e4fe9e7dc3828bf6a5714eb3c55aef6260d823a2 upstream.
+
+The EC field of the constructed ESR is conditionally modified by ORing in
+ESR_ELx_EC_DABT_LOW for a data abort.  However, ESR_ELx_EC_SHIFT is missing
+from this condition.
+
+Signed-off-by: Matt Evans <matt.evans@arm.com>
+Acked-by: Marc Zyngier <marc.zyngier@arm.com>
+Signed-off-by: Christoffer Dall <christoffer.dall@linaro.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ arch/arm64/kvm/inject_fault.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/arch/arm64/kvm/inject_fault.c
++++ b/arch/arm64/kvm/inject_fault.c
+@@ -162,7 +162,7 @@ static void inject_abt64(struct kvm_vcpu
+               esr |= (ESR_ELx_EC_IABT_CUR << ESR_ELx_EC_SHIFT);
+       if (!is_iabt)
+-              esr |= ESR_ELx_EC_DABT_LOW;
++              esr |= ESR_ELx_EC_DABT_LOW << ESR_ELx_EC_SHIFT;
+       vcpu_sys_reg(vcpu, ESR_EL1) = esr | ESR_ELx_FSC_EXTABT;
+ }