diff mbox

[Xen-devel,2/9] xen/arm: traps: Second attempt to correctly use the content of HPFAR_EL2

Message ID 1466601669-25398-3-git-send-email-julien.grall@arm.com
State New
Headers show

Commit Message

Julien Grall June 22, 2016, 1:21 p.m. UTC
Commit c051618 "xen/arm: traps: Correctly interpret the content of the
register HPFAR_EL2" attempted to fix the interpretation of HPFAR_EL2.

However, the register contains a 4KB-aligned address. This means that
the reported address is not directly usable to know the faulting IPA.
The offset in the 4KB page can be found by looking at the associated virtual
address (FAR_EL2/HDFAR).

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

---

Cc: Tamas K Lengyel <tamas@tklengyel.com>

I overlooked the usage of HPFAR_EL2. This is currently only affecting
memaccess. Rather that return that exact address, the address will
always be the base addres of the 4KB page.

This would need to be backported up to Xen 4.6.
---
 xen/arch/arm/traps.c | 12 ++++++++----
 1 file changed, 8 insertions(+), 4 deletions(-)
diff mbox

Patch

diff --git a/xen/arch/arm/traps.c b/xen/arch/arm/traps.c
index 0709deb..742f7d3 100644
--- a/xen/arch/arm/traps.c
+++ b/xen/arch/arm/traps.c
@@ -2371,11 +2371,15 @@  done:
     if (first) unmap_domain_page(first);
 }
 
-static inline paddr_t get_faulting_ipa(void)
+static inline paddr_t get_faulting_ipa(vaddr_t gva)
 {
     register_t hpfar = READ_SYSREG(HPFAR_EL2);
+    paddr_t ipa;
 
-    return ((paddr_t)(hpfar & HPFAR_MASK) << (12 - 4));
+    ipa = (paddr_t)(hpfar & HPFAR_MASK) << (12 - 4);
+    ipa |= gva & ~PAGE_MASK;
+
+    return ipa;
 }
 
 static void do_trap_instr_abort_guest(struct cpu_user_regs *regs,
@@ -2396,7 +2400,7 @@  static void do_trap_instr_abort_guest(struct cpu_user_regs *regs,
         };
 
         if ( hsr.iabt.s1ptw )
-            gpa = get_faulting_ipa();
+            gpa = get_faulting_ipa(gva);
         else
         {
             /*
@@ -2445,7 +2449,7 @@  static void do_trap_data_abort_guest(struct cpu_user_regs *regs,
 #endif
 
     if ( dabt.s1ptw )
-        info.gpa = get_faulting_ipa();
+        info.gpa = get_faulting_ipa(info.gva);
     else
     {
         rc = gva_to_ipa(info.gva, &info.gpa, GV2M_READ);