xen/arm: traps: Correctly interpret the content of the register HPFAR_EL2
authorJulien Grall <julien.grall@arm.com>
Fri, 22 Apr 2016 15:58:33 +0000 (16:58 +0100)
committerStefano Stabellini <sstabellini@kernel.org>
Wed, 27 Apr 2016 15:44:25 +0000 (16:44 +0100)
The register HPFAR_EL2 (resp. HPFAR on arm32) contains the bits [47:12]
(resp. [39:12]) of the faulting IPA. Unlike other registers that represent
an address, the upper bits of the IPA are stored in the register bits
[4:39] (resp. [4:21]).

However, Xen assumes that the register contains the faulting IPA correctly
offsetted. This will result to get a wrong IPA when the fault is happening
during a translation table walk. Note this is only affecting  memaccess.

Introduce a new helper to get the faulting IPA from HPFAR_EL2 and
replace direct read from the register by the helper.

Signed-off-by: Julien Grall <julien.grall@arm.com>
Reviewed-by: Andre Przywara <andre.przywara@arm.com>
Reviewed-by: Stefano Stabellini <sstabellini@kernel.org>
xen/arch/arm/traps.c
xen/include/asm-arm/processor.h

index 9abfc3cfcb10d2019b45fd0550cc7cc9af674fc6..2b8931c5c22e2b23cc93af04152d3cb8619add39 100644 (file)
@@ -2362,6 +2362,13 @@ done:
     if (first) unmap_domain_page(first);
 }
 
+static inline paddr_t get_faulting_ipa(void)
+{
+    register_t hpfar = READ_SYSREG(HPFAR_EL2);
+
+    return ((paddr_t)(hpfar & HPFAR_MASK) << (12 - 4));
+}
+
 static void do_trap_instr_abort_guest(struct cpu_user_regs *regs,
                                       const union hsr hsr)
 {
@@ -2380,7 +2387,7 @@ static void do_trap_instr_abort_guest(struct cpu_user_regs *regs,
         };
 
         if ( hsr.iabt.s1ptw )
-            gpa = READ_SYSREG(HPFAR_EL2);
+            gpa = get_faulting_ipa();
         else
         {
             /*
@@ -2430,7 +2437,7 @@ static void do_trap_data_abort_guest(struct cpu_user_regs *regs,
 #endif
 
     if ( dabt.s1ptw )
-        info.gpa = READ_SYSREG(HPFAR_EL2);
+        info.gpa = get_faulting_ipa();
     else
     {
         rc = gva_to_ipa(info.gva, &info.gpa, GV2M_READ);
index 7e6eb660ed6686ce3a46adb8d2879fc59eb1a161..6789cd04851c72775fc3abda5c0eae30af57b41f 100644 (file)
@@ -565,6 +565,13 @@ union hsr {
 
 #define FSC_LL_MASK    (_AC(0x03,U)<<0)
 
+/* HPFAR_EL2: Hypervisor IPA Fault Address Register */
+#ifdef CONFIG_ARM_64
+#define HPFAR_MASK     GENMASK(39, 4)
+#else
+#define HPFAR_MASK     GENMASK(31, 4)
+#endif
+
 /* Time counter hypervisor control register */
 #define CNTHCTL_EL2_EL1PCTEN (1u<<0) /* Kernel/user access to physical counter */
 #define CNTHCTL_EL2_EL1PCEN  (1u<<1) /* Kernel/user access to CNTP timer regs */